gpt4 book ai didi

c# - 附加类型的实体失败,因为相同类型的另一个实体已经具有相同的主键值

转载 作者:太空狗 更新时间:2023-10-29 18:01:31 24 4
gpt4 key购买 nike

错误消息:附加类型的实体失败,因为相同类型的另一个实体已经具有相同的主键值。

问题:如何以类似于下面代码中 AttachActivity 方法中演示的方式附加实体?

我必须假设上面错误消息的“另一个实体”部分指的是内存中存在但超出范围的对象 (??)。我注意到这一点是因为我尝试附加的实体类型的 DBSet 的 Local 属性返回零。

我有理由相信实体不存在于上下文中,因为我单步执行代码并在创建上下文时观察它。在创建 dbcontext 后立即将实体添加到几行中。

正在测试此处指定的附加实体:what is the most reasonable way to find out if entity is attached to dbContext or not?

在 visual studio 的本地窗口中查看本地时,除了我要附加的实体外,我看不到事件类型的实体(无论 ID 是什么)。

代码按以下顺序执行:Try -> ModifyProject -> AttachActivity

代码在注释行的 AttachActivity 中失败。

注意调试注释之间的代码,如果任何实体已添加到上下文中,这些代码将抛出。

private string AttachActivity(Activity activity)
{
string errorMsg = ValidateActivity(activity); // has no code yet. No. It does not query db.

if(String.IsNullOrEmpty(errorMsg))
{
// debug
var state = db.Entry(activity).State; // Detached
int activityCount = db.Activities.Local.Count;
int projectCount = db.Activities.Local.Count;

if (activityCount > 0 || projectCount > 0)
throw new Exception("objects exist in dbcontext");
// end debug
if (activity.ID == 0)
db.Activities.Add(activity);
else
{
db.Activities.Attach(activity); // throws here
db.Entry(activity).State = System.Data.Entity.EntityState.Modified;
}
}
return errorMsg;
}


public int ModifyProject(Presentation.PresProject presProject, out int id, out string errorMsg)
{
// snip

foreach (PresActivity presActivity in presProject.Activities)
{
Activity a = presActivity.ToActivity(); // returns new Activity object
errorMsg = ValidateActivity(a); // has no code yet. No. It does not query db.
if (String.IsNullOrEmpty(errorMsg))
{
a.Project = project;
project.Activities.Add(a);
AttachActivity(a);
}
else
break;
}
if (string.IsNullOrEmpty(errorMsg))
{
if (project.ID == 0)
db.Projects.Add(project);
else
db.AttachAsModfied(project);
saveCount = db.SaveChanges();
id = project.ID;
}
return saveCount;
}

这是更新 dbContext 的类:

public void Try(Action<IServices> work)
{
using(IServices client = GetClient()) // dbContext is newd up here
{
try
{
work(client); // ModifyProject is called here
HangUp(client, false);
}
catch (CommunicationException e)
{
HangUp(client, true);
}
catch (TimeoutException e)
{
HangUp(client, true);
}
catch (Exception e)
{
HangUp(client, true);
throw;
}
}

我不是在问:如何使用 AsNoTracking What difference does .AsNoTracking() make?

最佳答案

避免收到此错误的一种解决方案是使用 Find 方法。在附加实体之前,查询所需实体的 DbContext,如果实体存在于内存中,您将获得本地实体,否则将从数据库中检索实体。

private void AttachActivity(Activity activity)
{
var activityInDb = db.Activities.Find(activity.Id);

// Activity does not exist in database and it's new one
if(activityInDb == null)
{
db.Activities.Add(activity);
return;
}

// Activity already exist in database and modify it
db.Entry(activityInDb).CurrentValues.SetValues(activity);
db.Entry(activityInDb ).State = EntityState.Modified;
}

关于c# - 附加类型的实体失败,因为相同类型的另一个实体已经具有相同的主键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26879968/

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