概要
これはグーグルがうまくできていない奇妙なエラーです。
AssetOwnerレコードを作成して挿入しようとしています。しかし、2つのテーブルの外部キー関係が原因でエラー「System.Data.SqlClient.SqlException」が発生します。これは、(明らかに)私が試みているSQLステートメントとは何の関係もありません。
INSERTステートメントがFOREIGNKEY制約「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の更新されたバージョンで奇妙なグレムリンに気付くことがあります。したがって、私の最初の考えは、問題の関係を削除し、再生成し、関係を再作成し、再生成することでした。これは成功していません。
私はコードを数回ステップスルーしました-このアクションの前にコントローラーアクションに他の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");
}
おそらく手がかりは、私が作業しているオブジェクトがエラーをスローする「転送」(そのコードパスを下る)であるのに対し、「追加」または「削除」はどちらもエラーをスローせずに正常に機能するという事実です。それでも、コードは実質的に同じであり、DBテーブル内のすべての調整オブジェクトは外部キー制約を満たしています。
トラブルシューティングをさらに支援するために、スタックトレースを次に示します。
System.Data.SqlClient.SqlException(0x80131904):INSERTステートメントがFOREIGNKEY制約「FK_Adjustments_AdjustmentProcesses」と競合していました。データベース「TPS_2」、テーブル「dbo.AdjustmentProcesses」、列「ID」で競合が発生しました。ステートメントは終了されました。System.Data.SqlClient.SqlConnection.OnError(SqlException例外、ブールブレーク接続)でSystem.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()でSystem.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet BulkCopyHandler、TdsParserStateObject stateObj)at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()at System.Data.SqlClient.SqlDataReader.get_MetaData()atSystem.Data.SqlClient.SqlCommand。
C:\ Users \ tim.niven.KJRG \ Documents \ Visual Studio 2010 \ Projects \ TPS-trunk \ TPS \ TPS \ Models \ MainObjects \ TPSDataAccess.cs:line 169のTPS.Models.TPSDataAccess.SaveChanges()でTPS .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:line 257 at lambda_method(Closure、ControllerBase、Object [])at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext、IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2パラメーター)atSystem.Web.Mvc.ControllerActionInvoker。<>c__DisplayClass15.b__12()at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter、ActionExecutingContext preContext、Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
1フィルター、ActionDescriptor actionDescriptor、IDictionary`2パラメーター)at System .Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext、String actionName)
だから私は一日中これでテーブルに頭をぶつけてきました-どんな助けやガイダンスも大歓迎です。
乾杯、
ティム。