2011-08-16 28 views
12

我有一个用户表。从其他表中可以看到此表格对像CreatedBy这样的字段的引用。无法在对象'dbo.User'中插入重复键。 r n声明已终止

问题是,当我插入另一个表的行(例如'x')时,它会尝试将新用户插入到用户表中。

它应该做的是在CreatedBy作为现有用户的表'x'中插入一行。

使用Entity Framework 4.任何人都遇到过这样的问题吗?

+0

相关问题:http://stackoverflow.com/questions/5449724/entity-framework-code-first-cannot-insert-duplicate-key-in-object-db – Stefan

回答

31

您可以将实体与相关实体一起插入,也可以插入实体而不引用相关实体,只需引用现有实体即可。这取决于你编写的代码。

实施例1:

User user = GetUserFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put both order and related entity user into Added state 
    // because user is not attached to the context 

    context.SaveChanges(); 
    // creates new order and new user and sets the relationship between them 
} 

实施例2:

using (var context = new MyContext()) 
{ 
    User user = context.Users.SingleOrDefault(u => u.Id == 1); 
    // query attaches this user to this context 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 

实施例3:

User user = GetUserFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    context.Users.Attach(user); 
    // we attach explicitely to the context telling EF thereby 
    // that we know that this user exists in the DB 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 

编辑

实施例4:

int userId = GetUserIdFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    var user = new User { Id = userId }; 
    // we create a stub user entity with the correct primary key 
    // It's not necessary to set other properties 
    // to only set the relationship to the order 

    context.Users.Attach(user); 
    // we attach explicitely to the context telling EF thereby 
    // that we know that this user exists in the DB 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 
+0

我的问题的优秀演绎。只是我已经在做示例3.唯一的区别是,不是通过GetUserFromSomeWhere()获取用户;我通过WCF线传递用户对象作为参数...所以我失去了上下文。这导致实体框架也插入用户对象。因为它不知道已经存在。 我将不得不从客户端发送ID并根据服务器端的ID获取用户。或者我将不得不在模型中包含外键列......以便我可以做到这一点... order.CreatedBy.Id = id; –

+2

@Nilotpal:'GetUserFromSomeWhere()'在某种程度上是对WCF服务的模拟,或者通常你的'用户'实体与你在其中进行修改的上下文分离。使用外键属性通常是一个好主意。或者,您也可以使用“存根”用户实体并将其附加到上下文中:var user = new User {Id = userId}; context.Users.Attach(用户);'。对于'Attach',只需要设置主键属性即可。如果您只想设置与订单的关系,则其他属性可能保持为空。请参阅上面的“编辑”部分中的示例4。 – Slauma

+1

@Slauma - +1。优秀的例子。 –

相关问题