[英]Entity Framework not mapping parent id as foreign key in child table
我正在使用Entity Framework 5.0,我想在表中插入具有父子关系的行,即user
和user_role
。
user
包含列user_id, first_names, last_name
user_role
包含role_id, role_name, user_id
列
我已经设置了实体框架,并且还可以在设计器查看器中看到它们的关联,现在当我尝试执行代码时,发生约束异常,该异常表示user_id
未映射到user_role
表中
Microsoft实体框架-不起作用:
using (MicrosoftEntities context = new MicrosoftEntities())
{
USER user = new USER();
user.FIRST_NAMES = "u";
user.LAST_NAME = "u";
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10001, role_name ="a" });
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10002, role_name ="b" });
context.USERZs.Add(user);
context.SaveChanges();
}
Telerik实体框架-正常工作:
using (TelerikEntities context = new TelerikEntities())
{
Telerik_USER user1 = new Telerik_USER();
user1.FIRST_NAMES = "u";
user1.LAST_NAME = "u";
user1.Telerik_USER_ROLE.Add(new Telerik_USER_ROLE() { ROLE_ID = 10001 });
user1.Telerik_USER_ROLE.Add(new Telerik_USER_ROLE() { ROLE_ID = 10002 });
context.Add(user1);
context.SaveChanges();
}
我究竟做错了什么? 请帮帮我。
我被迫使用Microsoft Entity Framework。
实体框架类
public partial class USER
{
public USER()
{
this.USER_ROLE = new HashSet<USER_ROLE>();
}
public long USER_ID { get; set; }
public string FIRST_NAMES { get; set; }
public string LAST_NAME { get; set; }
public virtual ICollection<USER_ROLE> USER_ROLE { get; set; }
}
public partial class USER_ROLE
{
public long USER_ROLE_ID { get; set; }
public Nullable<long> USER_ID { get; set; }
public Nullable<long> ROLE_ID { get; set; }
public Nullable<string> ROLE_NAME { get; set; }
public virtual USER USER { get; set; }
}
在添加角色之前,用户必须存在。 您不能同时进行。 您应该在事务中执行此操作,但是我将发布插入内容的工作代码,而不是trans。
using (MicrosoftEntities context = new MicrosoftEntities())
{
USER user = new USER();
user.FIRST_NAMES = "u";
user.LAST_NAME = "u";
context.USERZs.Add(user);
context.SaveChanges();
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10001, role_name ="a", USER_ID = user.USER_ID });
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10002, role_name ="b", USER_ID = user.USER_ID });
context.SaveChanges();
}
问题是,你的新子实体不被跟踪EF在插入时(因为你newed
它们)。 如果您使用代理并让EF生成自己的ID,它应该可以工作。
常见的做法是在您的情况下,在SaveChanges()
之前附加实体:
using (MicrosoftEntities context = new MicrosoftEntities())
{
USER user = new USER();
user.FIRST_NAMES = "u";
user.LAST_NAME = "u";
/** Notice we don't specify a ROLE_ID here, we let EF generate it **/
user.USER_ROLE.Add(new USER_ROLE() { role_name ="a" });
user.USER_ROLE.Add(new USER_ROLE() { role_name ="b" });
/** attach all entities to the context **/
foreach(var role in user.USER_ROLE)
{
context.Entry(role).State = role.ROLE_ID == default(long) ? EntityState.Added : EntityState.Modified;
}
context.USERZs.Add(user);
context.SaveChanges();
}
在EF7中,您可以使用AttachGraph
(或TrackGraph
,不确定最终版本中的调用方式),而在TrackGraph
,您需要手工完成。
这可以通过使用代理,使用DbContext.Create
创建实体(而不是new
实体)并在USER_ROLE
上具有USER
(如果是0:n,我们不知道)的导航属性来进一步简化,并且在角色上设置User
属性:这将在保存时附加并设置正确的ID。
在我看来,您正在将数据库问题转移到ORM,并且应该从这些问题中抽象出来。 在ORM中生成自己的ID是没有意义的:如果事情很好(实际上不是),那么从理论上讲,拥有ORM应该完全不关心ID,而是将对象用于关系而非ID。
如果您打算在代码中使用ORM,请忽略EF和ORM,并获得一些SQL映射器(例如Dapper.NET或类似的东西),这确实令人惊奇,并且比EF具有更高的性能。
您需要先保存新User
以便获得数据库生成的ID(当然,当然是假定它是自动生成的):
using (MicrosoftEntities context = new MicrosoftEntities())
using(var transaction = context.DataBase.BeginTransaction())
{
USER user = new USER();
user.FIRST_NAMES = "u";
user.LAST_NAME = "u";
context.Users.Add(user);
context.SaveChanges();
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10001, role_name ="a", userId = user.Id});
user.USER_ROLE.Add(new USER_ROLE() { ROLE_ID = 10002, role_name ="b", userId = user.Id});
context.SaveChanges();
transaction.Commit();
}
仅适用于EF6 +
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.