2017-08-06 37 views
0
public partial class MyDbContext : DbContext 
{ 
    public MyDbContext() 
     : base("name=Model1") 
    { 
    } 

    public virtual DbSet<User> Users { get; set; } 
    public virtual DbSet<UserGroup> UserGroups { get; set; } 
    public virtual DbSet<UserGroupMember> UserGroupMembers { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { } 
} 

[Table("gnr.UserGroup")] 
public partial class UserGroup 
{ 
    public UserGroup() 
    { 
     ChildUserGroups = new HashSet<UserGroupMember>(); 
     UserGroupMembers = new HashSet<UserGroupMember>(); 
    } 

    public long ID { get; set; } 
    public string Title { get; set; } 
    public string Description { get; set; } 

    [InverseProperty("ChildUserGroup")] 
    public virtual ICollection<UserGroupMember> ChildUserGroupMembers { get; set; } 

    [InverseProperty("UserGroup")] 
    public virtual ICollection<UserGroupMember> UserGroupMembers { get; set; } 
} 

[Table("gnr.UserGroupMember")] 
public partial class UserGroupMember 
{ 
    public long ID { get; set; } 
    public long? UserID { get; set; } 
    public virtual User User { get; set; } 

    [ForeignKey("UserGroup")] 
    public long UserGroupID { get; set; } 
    public virtual UserGroup UserGroup { get; set; } 

    [ForeignKey("ChildUserGroup")] 
    public long? ChildUserGroupID { get; set; } 
    public virtual UserGroup ChildUserGroup { get; set; } 

} 

[Table("gnr.User")] 
public partial class User 
{ 
    public User() 
    { 
     UserGroupMembers = new HashSet<UserGroupMember>(); 
    } 

    public long ID { get; set; } 
    public string Username { get; set; } 
    public string MobileNumber { get; set; } 
    public virtual ICollection<UserGroupMember> UserGroupMembers { get; set; } 
} 


     static void Main(string[] args) 
    { 
     WorkNotCorrectly(); 

     Console.WriteLine("Done"); 

     Console.ReadLine(); 
    } 

    private static void WorkNotCorrectly() 
    { 
     using (var db = new MyDbContext()) 
     { 
      var ug = new UserGroup { Title = "It's a new UserGroup 1" }; 

      var cugm = new UserGroupMember { ChildUserGroupID = 1 }; 

      ug.ChildUserGroupMembers.Add(cugm); 

      // After This Line 
      db.UserGroups.Add(ug); 

的MyDbContext設置「cugm」對象「ChildUserGroup」屬性設置爲「微克」實體框架的DbContext混亂當同桌指着

但預期的行爲兩個外鍵是設置「 cugm用戶組」的特性 '' 對象的 '微克'

'微克' 對象到JSON:

{ 
"ID": 0, 
"Title": "It's a new UserGroup 1", 
"Description": null, 
"ChildUserGroupMembers": [ 
    { 
     "ID": 0, 
     "UserID": null, 
     "User": null, 
     "UserGroupID": 0, 
     "UserGroup": null, 
     "ChildUserGroup": HERE IS THE PROBLEM => The MyDbContext sets the 'ChildUserGroup' property instead of 'UserGroup' property, 
     "ChildUserGroupID": 1 
    } 
], 
"UserGroupMembers": [] 
} 

而且調用SaveChanges:

  db.SaveChanges(); 
     } 
    } 

'微克' 對象到JSON後的SaveChanges:

{ 
    "ID": 2, 
    "Title": "It's a new UserGroup 1", 
    "Description": null, 
    "ChildUserGroupMembers": [ 
     { 
      "ID": 1, 
      "UserID": null, 
      "User": null, 
      "UserGroupID": 2, 
      "ChildUserGroupID": 2 WHAT???? IT IS CHANGED TO 2 (THE NEW UserGroup THAT IS GENERATED), 
      "ChildUserGroup": HERE IS THE PROBLEM => The MyDbContext sets the 'ChildUserGroup' property instead of 'UserGroup' property 
     } 
    ], 
    ????? WHAT IS THIS??? WHY UserGroupMembers PROPERTY IS FILLED 
    "UserGroupMembers": [ 
     { 
      "ID": 1, 
      "UserID": null, 
      "User": null, 
      "UserGroupID": 2, 
      "ChildUserGroupID": 2 
     } 
    ] 
} 

預期的行爲,結果是:

{ 
    "ID": 2, 
    "Title": "It's a new UserGroup 1", 
    "Description": null, 
    "ChildUserGroupMembers": [ 
     { 
      "ID": 1, 
      "UserID": null, 
      "User": null, 
      "UserGroupID": 2, 
      "UserGroup": 'The ug object with ID of 2 ', 
      "ChildUserGroupID": 1 
     } 
    ] 
} 

Result in SSMS and the relationship diagram

看來,EF困惑,以確定正確的FK,在插入物體和由我填充的物體後必須自己填充的物體?!!

更新: 這是實體之間的關係:

  1. UserGroupMember是用戶組和用戶之間的橋樑表

  2. 可以爲每個用戶1個... *用戶組

    成員
  3. 每個用戶組可以有1 ... *用戶作爲成員

(在此之前它像一個正常的橋接表來表示多對多的關係)

4.每個用戶組可以有1 ... * ChildUserGroup作爲成員

(這意味着一個UserGroup可以有一個User或一個ChildUserGroup作爲成員,就像Windows的'用戶和組')

真誠。

+1

https://stackoverflow.com/help/mcve – mjwills

+0

你能解釋ChildUserGroup是什麼?它是兩個UserGroups之間的關係,還是它是另一個UserGroup的成員UserGroup?你的模型似乎混淆了兩者之間。 –

+0

鑑於'ChildUserGroup'和'ChildUserGroupMembers'是一對關係,你爲什麼認爲向'ChildUserGroupMembers'集合中添加'cugm'不應該將'ChildUserGroup'設置爲'ug'? – Smit

回答

0

這裏的主要問題是,您的代碼設置的導航屬性不符合您的期望。

首先,您正在使用InverseProperty屬性來定義您的關係。

  • UserGroup.ChildUserGroupMembers & UserGroupMember.ChildUserGroup構成與外鍵屬性的一個關係,ChildUserGroupID
  • UserGroup.UserGroupMembers & UserGroupMember.UserGroup構成與國外關鍵屬性爲UserGroupID

在EF相互之間的關係,當你定義一個關係,有3個組件,主要到相關導航,從屬到主要導航&外鍵屬性。其中任何一個的設定值也會決定其他人。如果您設置了任何導航,那麼外鍵屬性將被設置爲與主鍵屬性具有相同的值。如果導航已經加載到內存中,導航也會被填充。

當SSMS輸出顯示時,您的UserGroup表中ID = 1的數據已經存在。 現在在你的代碼,

  • 您正在創建一個新的UserGroupug
  • 您正在創建新的UserGroupMembercugm
  • 您正在設定的值爲cugm.ChildUserGroupID = 1.給定的關係實體具有,cugm.ChildUserGroup導航(它與ChildUserGroupID fk關聯),應該有UserGroup ID = 1分配給它。由於它沒有加載到內存中,導航將保持爲空。如果將ID = 1的UserGroup加載到內存中的方式與UserGroup.ChildUserGroupMembers集合加載cugm的方式相同。
  • 然後您將cugm添加到ug.ChildUserGroupMembers集合。意思是FK屬性cugm.ChildUserGroupID應取值爲ug.ID。而逆導航的cugm.ChildUserGroup應該指向ug。由於直到這一點EF不在圖片中,所以直到添加實體纔會發生以上變化。
  • 然後,您將ug添加到UserGroups db集,以便EF將開始跟蹤實體及其子級。由於ug.ChildUserGroupMembers系列已添加cugm,因此EF將cugm.ChildUserGroup設置爲ugug對象仍然有臨時密鑰,因此EF不會複製ug.IDcugm.ChildUserGroupID

那就是如何你有你的第一個JSON。它有ChildUserGroup集,因爲您設置了它的逆向導航。

一旦您調用SaveChanges, EF會將實體ug保存到數據庫。由於您的數據庫已經擁有ID爲1的實體,因此它將獲得下一個ID爲2.由於ug.ID不再是臨時值,因此cugm.ChildUserGroupID將取其值並更改爲2

現在根據您的SSMS數據, 您要創建新的UserGroup對象 - ug,保存時將獲得ID = 2。您要創建新的UserGroupMember對象 - cugm,它將得到ID = 1(帶有標識列的第一行。)cugm.UserGroupId = 2因此cugm.UserGroup導航應設置爲ug & cugm.ChildUserGroupID = 1。

這是代碼應該是什麼樣子

var ug = new UserGroup { Title = "It's a new UserGroup 1" }; 
var cugm = new UserGroupMember { ChildUserGroupID = 1 }; 

ug.UserGroupMembers.Add(cugm); // You want to set UserGroupID = 2 so cugm should be added to its corresponding inverse navigation 

db.UserGroups.Add(ug); 

db.SaveChanges(); 

上面的代碼會產生精確的記錄如您在數據庫中想要的。

ug對象的JSON輸出會像下面(這也是不正確的在你的問題)

{ 
    "ID": 2, 
    "Title": "It's a new UserGroup 1", 
    "Description": null, 
    "UserGroupMembers": [{ 
     "ID": 1, 
     "UserID": null, 
     "User": null, 
     "UserGroupID": 2, 
     "UserGroup": ... // Pointing to UserGroup with ID = 2 
     "ChildUserGroupID": 1, 
     "ChildUserGroup": null 
    }] 
} 
+0

非常感謝你,設計很棘手,我感到困惑,你讓我清楚,真誠。 – HaMEd