概述
这是一个奇怪的错误,谷歌搜索得不好。
我尝试创建并插入 AssetOwner 记录。但是由于两个表上的外键关系(显然)与我正在尝试的 SQL 语句无关,我收到错误“System.Data.SqlClient.SqlException”:
INSERT 语句与 FOREIGN KEY 约束“FK_Adjustments_AdjustmentProcesses”冲突。冲突发生在数据库“TPS_2”、表“dbo.AdjustmentProcesses”、列“ID”中。该语句已终止。
细节
这是引发错误的代码片段(由注释指示)(“da”就像一个存储库):
var add = new AssetOwner()
{
Client = da.Clients.Get(adjustment.ToClientID),
Asset = da.Assets.Get(adjustment.AssetID),
StartDate = adjustment.EffectiveDate
};
da.AssetOwners.Add(add);
var remove = da.AssetOwners.GetCurrentOwner(da.Assets.Get(adjustment.AssetID));
remove.EndDate = adjustment.EffectiveDate;
da.SaveChanges(); // Exception here (this is DataContext.SubmitChanges())
此处相关的表和关系的小图:
引发错误的关系以红色突出显示,有问题的表格以红色圈出 - 如您所见,AssetOwner 的插入似乎与 Adjustment-AdjustmentProcess 关系没有太大关系?
故障排除
我正在使用 Visual Studio 生成的 LINQ-to-SQL 类,有时我注意到我的 DataContext 的刷新版本中有奇怪的 gremlins。因此,我的第一个想法是删除有问题的关系,重新生成,重新创建关系,重新生成。这并没有成功。
我已经对代码进行了几次单步调试——值得注意的是,在此之前的控制器操作中没有其他 SQL 语句——而且我无法看到任何可能导致此异常的原因。尽管如此,我将在这里重现整个控制器操作(希望长代码片段不会阻止任何潜在的读者):
public ActionResult ManualEntry(int id, FormCollection collection)
{
// Grab the adjustment process
var process = da.AdjustmentProcesses.Get(id);
// Map a dto and set the details needed for the view
var dto = new AdjustmentProcessViewModel();
Adapter.MapDto(dto, process, da);
Adapter.SetDetails(dto, da);
// Generate the premium values for those policies we can
var pg = new PremiumGenerator(da);
foreach (var apd in dto.AdjustmentPolicyDetails)
{
if (apd.CanAutoGenerate == true)
pg.GeneratePremiumValues(dto.Policies[apd.Index]);
}
// Update the model from the form collection
TryUpdateModel(dto.Policies, "Policies");
// Run Validation
var invalids = 0;
foreach (var apd in dto.AdjustmentPolicyDetails)
{
var policy = dto.Policies[apd.Index];
var validator = new PolicyValidator(da);
validator.Validate(policy);
if (!validator.IsValid)
{
invalids++;
foreach (var ruleViolation in validator.RuleViolations)
apd.RuleViolations.Add(new RuleViolation(ruleViolation.ErrorMessage, "Policies[" + apd.Index.ToString() + "]." + ruleViolation.PropertyName));
this.MergeRuleViolations(apd.RuleViolations);
}
}
// If validation has failed, return the view
if (invalids > 0)
return View(dto);
else // Otherwise process the adjustments
{
foreach (var adjustment in da.Adjustments.GetAdjustmentsForProcess(process.ID))
{
if (adjustment.ActionID == (int)AdjustmentAction.Add)
{
var add = new AssetOwner()
{
Client = da.Clients.Get(adjustment.ClientID),
Asset = da.Assets.Get(adjustment.AssetID),
StartDate = adjustment.EffectiveDate
};
da.AssetOwners.Add(add);
da.SaveChanges();
}
else if (adjustment.ActionID == (int)AdjustmentAction.Remove)
{
var remove = da.AssetOwners.GetCurrentOwner(da.Assets.Get(adjustment.AssetID));
remove.EndDate = adjustment.EffectiveDate;
da.SaveChanges();
}
else if (adjustment.ActionID == (int)AdjustmentAction.Transfer)
{
var add = new AssetOwner()
{
Client = da.Clients.Get(adjustment.ToClientID),
Asset = da.Assets.Get(adjustment.AssetID),
StartDate = adjustment.EffectiveDate
};
da.AssetOwners.Add(add);
var remove = da.AssetOwners.GetCurrentOwner(da.Assets.Get(adjustment.AssetID));
remove.EndDate = adjustment.EffectiveDate;
da.SaveChanges();
}
}
var policyAdapter = new PolicyAdapter();
foreach (var policy in dto.Policies)
{
var newPolicy = new Policy();
policyAdapter.MapObject(newPolicy, policy, da);
var validator = new PolicyValidator(da);
validator.Validate(newPolicy);
if (!validator.IsValid)
throw new Exception();
else
{
da.Policies.Add(newPolicy);
da.SaveChanges();
}
}
}
return RedirectToAction("Index");
}
也许一个线索是我正在处理的对象是引发错误的“传输”(沿着该代码路径向下),而“添加”或“删除”都可以正常工作而不会引发错误。尽管如此,代码实际上是相同的,并且数据库表中的所有调整对象都满足外键约束。
为了进一步帮助排除故障,这里是堆栈跟踪:
System.Data.SqlClient.SqlException (0x80131904):INSERT 语句与 FOREIGN KEY 约束“FK_Adjustments_AdjustmentProcesses”冲突。冲突发生在数据库“TPS_2”、表“dbo.AdjustmentProcesses”、列“ID”中。该语句已终止。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 在 System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 在 System.Data.SqlClient.SqlDataReader.get_MetaData() 在 System.Data.SqlClient.SqlCommand。
在 C:\Users\tim.niven.KJRG\Documents\Visual Studio 2010\Projects\TPS-trunk\TPS\TPS\Models\MainObjects\TPSDataAccess.cs:TPS 中的 TPS.Models.TPSDataAccess.SaveChanges() 中:第 169 行.Areas.Clients.Controllers.AdjustmentProcessController.ManualEntry(Int32 id, FormCollection 集合) 在 C:\Users\tim.niven.KJRG\Documents\Visual Studio 2010\Projects\TPS-trunk\TPS\TPS\Areas\Clients\Controllers \AdjustmentProcessController.cs:在 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary 的 lambda_method(Closure , ControllerBase , Object[] ) 的第 257 行2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2 个参数)在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 过滤器,ActionExecutingContext preContext,Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
1 过滤器,ActionDescriptor actionDescriptor,IDictionary`2 参数)在 System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.b__12() .Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
因此,我整天都在用这个来敲打我的头 - 任何帮助或指导将不胜感激。
干杯,
蒂姆。