0

给定以下示例:

public class Parent 
{
    public Guid ID {get;set;}
    public string Name {get;set;}
    public Child Child {get;set;}
}


public class Child 
{
    public Guid ID {get;set;}
    public string Name {get;set;}
}

我想保存一个父对象实例,并为其分配一个子实例。这里的事实是:给定的子对象已经存在于数据库中,

 Parent p = new Parent();
 p.ID = Guid.NewGuid();

 // Get the Child Object 
 Child c = GetTheChild(...);
 p.Child = c;

SaveParent ( p );

在函数Save Parent中,实现了以下代码:

public void SaveParent ( Parent p )
{
     using (MyContext context = new ClinicContext())
     {
        context.Parents.Add( P );
        context.SaveChanges();

     }
}

现在问题来了:由于本例中的child已经存在于数据库中,但是当在上下文DBSet中添加parent时,给定的实体c也持有“Added”的入口状态,你猜怎么着?DBContext 尝试使用重复的 Key 保存另一个子记录!

任何机构都知道如何解决这个问题?如果实体框架可以检测到数据库中已经存在的记录,我正在考虑是否有办法将插入转换为更新。

谢谢你的帮助。

4

3 回答 3

0

如果您添加一个实体,所有相关实体都将被添加。如果您附加一个实体,所有相关实体都将被附加。在您的情况下,您要添加父实体,然后附加子实体。您还可以尝试使用外键并添加父级,然后将外键设置为相关的子 ID。这样您就不必将实体带到客户端来创建关系(尽管您需要知道相关实体的键)。

于 2013-01-24T06:40:38.017 回答
0

我猜 GetTheChild() 会从数据库中返回一个孩子。因此,您需要做的就是在调用 SaveChanges 之前调用 ChangeObjectState 方法将子项标记为 Unchanged。

var osm = context.ObjectStateManager;
osm.ChangeObjectState(child, EntityState.Unchanged);
于 2013-01-24T07:39:53.207 回答
0

你怎么接孩子?子项应附加到您保存父项的同一上下文。

我的猜测是您的 GetTheChild 函数使用了一个新的上下文 - 这意味着当您返回时,孩子是分离的,并且出于所有意图和目的,EF 认为它已被“添加”

正如面板所说,您可以只添加一个外键并设置孩子的密钥而不是孩子本身,但似乎有一些您应该解决的设计问题。

于 2013-01-24T07:22:24.700 回答