簡體   English   中英

實體框架未將父ID映射為子表中的外鍵

[英]Entity Framework not mapping parent id as foreign key in child table

我正在使用Entity Framework 5.0,我想在表中插入具有父子關系的行,即useruser_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM