与 REFERENCE 约束冲突。如何解决这个问题?
Conflicted with the REFERENCE constraint. How to solve this?
我捕获了这个 GenericADOException
异常,但是当我执行 genRep.Update(userW)
时又出现了一些意外的异常。我该如何解决这个问题?这是我的代码:
public ActionResult DeleteUser(long? UserID)
{
GenericRepositoryV2 genRep ;
if (!SecurityService.IsLoggedIn(Session))
{
return SecurityService.LoginAndRedirect(Request);
}
try
{
genRep = new GenericRepositoryV2();
genRep.StartTransaction();
User user = genRep.GetById<User>(UserID);
if (user == null)
{
found = false;
}
else
{
UserWrapper userW = genRep.GetByIdUser(UserID);
genRep.Remove<User>(userW);
genRep.EndTransaction();
}
}
catch (GenericADOException gae)
{
if (gae.InnerException.Message.IndexOf("REFERENCE constraint") != -1)
{
genRep = new GenericRepositoryV2();
genRep.StartTransaction();
UserWrapper userW = genRep.GetByIdUser(Convert.ToInt64(UserID));
userW.Status = UserStatus.PendingDelete;
genRep.Update(userW);
genRep.Flush();
genRep.EndTransaction();
}
//_log.Error("An error has occured while deleting the user.");
}
catch (Exception e)
{
_log.Error("Unexpected, unhandled exception: ", e);
}
return RedirectToAction(viewAllUsers);
}
希望有人帮助我!
提前谢谢你
更新 1:
异常:
NHibernate.Exceptions.GenericADOException was caught
HResult=-2146232832
Message=could not execute batch command.[SQL: SQL not available]
Source=NHibernate
SqlString=SQL not available
StackTrace:
at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatchWithTiming(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch()
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at OmanERP.Persistence.GenericRepositoryV2.EndTransaction() in e:\OmanERP\OmanERP\Persistence\GenericRepositoryV2.cs:line 583
at OmanERP.Controllers.UserController.DeleteUser(Nullable`1 UserID) in e:\OmanERP\OmanERP\Controllers\UserController.cs:line 144
InnerException: System.Data.SqlClient.SqlException
HResult=-2146232060
Message=The DELETE statement conflicted with the REFERENCE constraint "FK48A70817829118FC". The conflict occurred in database "OmanERP_Harpreet", table "dbo.Invoices", column 'GeneratedByID'.
The statement has been terminated.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=1
Number=547
Procedure=""
Server=192.168.1.20
State=0
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand()
at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery()
at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery()
at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
InnerException:
根据该错误判断,您的存储库正试图从其 table 中删除用户,但该用户在另一个 table (dbo.Invoices) 中被引用。
因此,当您尝试删除主键在另一个 table 中作为外键引用的记录时,您看到了外键约束错误。
发票上的 GeneratedById table 是否可以为空?如果是,则在 Nhibernate 中设置级联规则,以便在删除父实体用户时清空 GeneratedById。
但是,一种常见的方法是从不完全删除任何记录,而是在该实体上设置一个字段以表示其已删除,例如名为 IsDeleted(位)或 DeletedOn(日期时间)的字段并隐藏记录"soft" 从 UI 删除。
谢谢大家给我的建议
我终于找到了我自己的解决方案 problem.I 只需创建一个 Rollback() 事务方法,即 "genRep.RollbackTransaction()" 并创建一个新的 session()。因为 Flush() 之后的 Nhibernate 刷新会话。
回滚方法:
public void RollbackTransaction()
{
if (null != this._trans && this._trans.IsActive)
{
this._trans.Rollback();
}
}
这是我的代码:
catch (GenericADOException gae)
{
if (gae.InnerException.Message.IndexOf(referenceConstraint) != -1)
{
genRep.RollbackTransaction();
genRep.NewSession();
UserWrapper userW = genRep.GetByIdUser(Convert.ToInt64(UserID));
userW.Status = UserStatus.PendingDelete;
genRep.Update(userW);
}
}
catch (Exception e)
{
_log.Error("Unexpected, unhandled exception: ", e);
}
}
我捕获了这个 GenericADOException
异常,但是当我执行 genRep.Update(userW)
时又出现了一些意外的异常。我该如何解决这个问题?这是我的代码:
public ActionResult DeleteUser(long? UserID)
{
GenericRepositoryV2 genRep ;
if (!SecurityService.IsLoggedIn(Session))
{
return SecurityService.LoginAndRedirect(Request);
}
try
{
genRep = new GenericRepositoryV2();
genRep.StartTransaction();
User user = genRep.GetById<User>(UserID);
if (user == null)
{
found = false;
}
else
{
UserWrapper userW = genRep.GetByIdUser(UserID);
genRep.Remove<User>(userW);
genRep.EndTransaction();
}
}
catch (GenericADOException gae)
{
if (gae.InnerException.Message.IndexOf("REFERENCE constraint") != -1)
{
genRep = new GenericRepositoryV2();
genRep.StartTransaction();
UserWrapper userW = genRep.GetByIdUser(Convert.ToInt64(UserID));
userW.Status = UserStatus.PendingDelete;
genRep.Update(userW);
genRep.Flush();
genRep.EndTransaction();
}
//_log.Error("An error has occured while deleting the user.");
}
catch (Exception e)
{
_log.Error("Unexpected, unhandled exception: ", e);
}
return RedirectToAction(viewAllUsers);
}
希望有人帮助我! 提前谢谢你
更新 1:
异常:
NHibernate.Exceptions.GenericADOException was caught
HResult=-2146232832
Message=could not execute batch command.[SQL: SQL not available]
Source=NHibernate
SqlString=SQL not available
StackTrace:
at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatchWithTiming(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch()
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at OmanERP.Persistence.GenericRepositoryV2.EndTransaction() in e:\OmanERP\OmanERP\Persistence\GenericRepositoryV2.cs:line 583
at OmanERP.Controllers.UserController.DeleteUser(Nullable`1 UserID) in e:\OmanERP\OmanERP\Controllers\UserController.cs:line 144
InnerException: System.Data.SqlClient.SqlException
HResult=-2146232060
Message=The DELETE statement conflicted with the REFERENCE constraint "FK48A70817829118FC". The conflict occurred in database "OmanERP_Harpreet", table "dbo.Invoices", column 'GeneratedByID'.
The statement has been terminated.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=1
Number=547
Procedure=""
Server=192.168.1.20
State=0
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand()
at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery()
at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery()
at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
InnerException:
根据该错误判断,您的存储库正试图从其 table 中删除用户,但该用户在另一个 table (dbo.Invoices) 中被引用。
因此,当您尝试删除主键在另一个 table 中作为外键引用的记录时,您看到了外键约束错误。
发票上的 GeneratedById table 是否可以为空?如果是,则在 Nhibernate 中设置级联规则,以便在删除父实体用户时清空 GeneratedById。
但是,一种常见的方法是从不完全删除任何记录,而是在该实体上设置一个字段以表示其已删除,例如名为 IsDeleted(位)或 DeletedOn(日期时间)的字段并隐藏记录"soft" 从 UI 删除。
谢谢大家给我的建议
我终于找到了我自己的解决方案 problem.I 只需创建一个 Rollback() 事务方法,即 "genRep.RollbackTransaction()" 并创建一个新的 session()。因为 Flush() 之后的 Nhibernate 刷新会话。
回滚方法:
public void RollbackTransaction()
{
if (null != this._trans && this._trans.IsActive)
{
this._trans.Rollback();
}
}
这是我的代码:
catch (GenericADOException gae)
{
if (gae.InnerException.Message.IndexOf(referenceConstraint) != -1)
{
genRep.RollbackTransaction();
genRep.NewSession();
UserWrapper userW = genRep.GetByIdUser(Convert.ToInt64(UserID));
userW.Status = UserStatus.PendingDelete;
genRep.Update(userW);
}
}
catch (Exception e)
{
_log.Error("Unexpected, unhandled exception: ", e);
}
}