2012-03-31 63 views
2

我有兩個類,用戶和角色,定義爲:NHibvernate 3.2多對多不填充連接表

public class User : Entity 
{ 
    // other properties ... 
    public virtual string Username 
    public virtual ICollection<Role> Roles { get; set; } 
} 

public class Role : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual ICollection<User> Users { get; set; } 
} 

在我的映射代碼,我有以下幾點:

mapper.Class<User>(map => 
{ 
    map.Bag(x=>x.Roles, 
     cm=> 
     { 
      cm.Table("UserRole"); 
      cm.Cascade(Cascade.All); 
      cm.Key(k => k.Column("[User]")); 
     }, 
     em=> 
     { 
      em.ManyToMany(mm => 
      { 
       mm.Column("[Role]"); 
      }); 
     }); 

}); 

mapper.Class<Role>(map => 
{ 
    map.Bag(x=>x.Users, 
     cm=> 
     { 
      cm.Inverse(true); 
      cm.Table("UserRole");       
      cm.Key(k=>k.Column("[Role]")); 
     }, 
     em => 
     { 
      em.ManyToMany(mm => 
      { 
       mm.Column("[User]"); 
      }); 
     }); 
}); 

的映射生成預期的模式,但連接表從不填充。在集合中添加一個新角色的新用戶會將角色和用戶保存到相應的表中,但連接表保留爲空。爲什麼?

編輯:我還沒有取得任何進展。我非常肯定映射是正確的,並且生成了正確的模式,但連接表根本沒有被填充。出於測試目的,我使用NBuilder像這樣產生的實體:

var roles = new Role[] 
{ 
    new Role("Admin"), 
    new Role("Manager"), 
    new Role("User") 
}; 

var users = Builder<User>.CreateListOfSize(10) 
    .TheFirst(1) 
     .Do(x => 
      { 
       x.Roles.Add(roles[0]); 
       x.Roles.Add(roles[1]); 
       roles[0].Users.Add(x); 
       roles[1].Users.Add(x); 
      }) 
    .All() 
     .With(x => x.Id = 0) 
     .And(x => x.Version = 0) 
     .And(x => x.Username = "test user") 
     .And(x => x.Password = "test password") 
     .Do(x => 
     { 
      x.Roles.Add(roles[2]); 
      roles[2].Users.Add(x); 
     } 
    .Build(); 


foreach (var u in users) session.Save(u); 

用戶和角色實體正確地持久,但連接表保持爲空。這意味着我以後無法有效地查詢給定用戶的角色,從而使這一點無效。

回答

0

我最終下載了NHibernate源代碼並直接引用,這樣我就可以通過它了。事實證明,這與我的生成測試數據的代碼未包含在顯式會話事務中有關。一旦我補充說,這很好。我很想看到關於這方面的一些解釋,因爲我無法非常清楚地遵守代碼,但我至少對問題解決表示滿意。

+0

很好,你想通了! – 2012-04-01 17:21:30

+0

另外我認爲,session.Flush();保存後也應該工作(沒有明確的交易)。用戶和角色在不需要交易的情況下被保存,因爲在NH可以將記錄保存到交叉表之後,NH需要從數據庫獲得反饋(如自動生成的ID)。 – 2012-04-01 17:33:32

+0

不要試圖通過使用flush來解決此問題。 nhibernate被設計爲使用明確的轉換,所以你想擁抱這一點。見例如NHProf文檔:http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions – 2012-04-01 18:27:05

1

確保您有兩個類相互引用。

我認爲代碼,類似於下面一個,應該爲你工作:

role.Users.Add(user);  
user.Roles.Add(role); 

session.Save(user); // NH only saves user and role, so it can get auto-generated identity fields 
session.Flush(); // NH now can save into cross-ref table, because it knows required information (Flush is also called inside of Transaction.Commit()) 

我發現了一個good answer的一個問題關於多到許多與很多來自NH文檔的解釋和報價。我認爲它值得閱讀。

[編輯]

在回答this somewhat similar問題存在其中需要明確的事務保存到交叉表中提到的討論。

我還編輯了上面的代碼,並添加了session.Flush()來反映我的發現。