实体框架:DBContext:如何检测数据库中存在的实体

时间:2013-01-24 06:17:54

标签: entity-framework

给出以下示例:

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对象实例,并为其分配一个Child实例。这里的事实是:给定的子对象已存在于数据库中,

 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();

     }
}

现在问题出现了:因为这个例子中的子节点已经存在于数据库中,但是当在上下文DBSet中添加父节点时,给定的实体c也保持条目状态为“已添加”,猜猜是什么? DBContext尝试使用重复的密钥保存另一个子记录!

任何人都知道如何解决这个问题?如果实体框架可以检测到数据库中已存在的记录,我在想是否有办法将Insert转换为Update。

感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

你是如何生孩子的?应将子项附加到您保存父项的相同上下文中。

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

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

答案 2 :(得分:0)

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

var osm = context.ObjectStateManager;
osm.ChangeObjectState(child, EntityState.Unchanged);