gpt4 book ai didi

c# - 当数据已在数据库中时 EF 种子不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 23:23:58 25 4
gpt4 key购买 nike

第一次创建数据库并运行 Seed 方法时效果很好。当数据已经在数据库中时,它会在第二次运行时抛出错误。

我还注意到,当我将属性分配给实体时,它的 PropertyId 没有更新并保持为空。

这是我的代码。

protected override void Seed(StreetStats.Data.StreetStatsDbContext context)
{
if (System.Diagnostics.Debugger.IsAttached == false)
System.Diagnostics.Debugger.Launch();

using (context.Database.BeginTransaction())
{
try
{
Worker worker = new Worker()
{
Name = "Worker 1",
};

context.Workers.AddOrUpdate(w => w.Name, worker);
context.SaveChanges(); //Worker gets Id assigned to the existing worker with the same name in DB

Job job = new Job()
{
Name = "Job 1",
Worker = worker
};

context.Jobs.AddOrUpdate(j => j.Name, job);
context.SaveChanges(); //WorkerId is null for some reason

MonitoringTask monitoringTask = new MonitoringTask
{
Job = job,
Name = "Task 1"
};

context.MonitoringTasks.AddOrUpdate(mt => mt.Name, monitoringTask);
context.SaveChanges(); //Throws exception

Area area = new Area
{
MonitoringTask = monitoringTask,
Name = "Area 1"
};

context.Areas.AddOrUpdate(a => a.Name, area);
context.SaveChanges();

context.Database.CurrentTransaction.Commit();
}
catch (Exception)
{
context.Database.CurrentTransaction.Rollback();
throw;
}
}
}

这是第三次 SaveChanges 的异常消息:

The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_dbo.MonitoringTasks_dbo.Jobs_JobId". The conflict occurred in database "StreetStats", table "dbo.Jobs", column 'Id'.

每个FK关系看起来都像

Worker Worker { get; set; }
Int64 WorkerId { get; set; }

最佳答案

在第二次运行 AddOrUpdate 调用后,查看 job 的实体状态。你可以这样做:

Debug.WriteLine(context.Entry(job).State);

您会看到它是Detached。不过,如果你这样做......

Debug.WriteLine(context.Jobs.Local.First().Name);

...您会发现实际上作业是依附于上下文的!

这是一个 known bugAddOrUpdate 中。实际附加到上下文的实例在您的方法范围内是隐藏的,job 是 EF 不知道的第二个实例。

这会导致各种痛苦。您使用 monitoringTask 连接的作业将被视为一个新实例,EF 将尝试插入它。我不确定为什么会出现外键异常(我本以为会违反唯一键),但我认为这与主键列类型以及它是否具有标识规范有关。

无论如何,变通办法是...

context.Workers.AddOrUpdate(w => w.Name, worker);
context.SaveChanges();
worker = context.Workers.Local.Single(w => w.Name == worker.Name);

...等等,对于您打算稍后使用对象的每个 AddOrUpdate 调用。这使得实际附加(但隐藏)的对象与您可见的对象相同。

关于c# - 当数据已在数据库中时 EF 种子不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34404198/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com