0

概述

这是一个奇怪的错误,谷歌搜索得不好。

我尝试创建并插入 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, IDictionary2 个参数)在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 过滤器,ActionExecutingContext preContext,Func 1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 过滤器,ActionDescriptor actionDescriptor,IDictionary`2 参数)在 System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.b__12() .Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

因此,我整天都在用这个来敲打我的头 - 任何帮助或指导将不胜感激。

干杯,

蒂姆。

4

1 回答 1

1

最后很愚蠢(通常是这样):这当然是在动作中更进一步的一些其他代码,其中一个适配器方法正在操作从数据库中检索到的对象,它不应该是。

一旦我隔离了引发异常的代码并且它工作了,我改变了事情的顺序,发现异常不是在 AssetOwner 的插入上引发的。因此,我在整个代码中的多个位置调用了 DataContext.SubmitChanges() 以找出导致问题的位置 - 已找到并已修复。

于 2012-04-19T23:29:50.050 回答