2010-04-20 52 views
11

我使用Fluent NHibernate爲我的應用程序映射一組成員類。我將這些類映射到asp.net成員資格數據庫結構。與問題相關的數據庫架構如下所示:Fluent NHibernate - 如何映射存在於兩個連接表中的不可爲空的外鍵

ASPNET_USERS 
UserId  PK 
ApplicationId FK NOT NULL 
other user columns ... 

ASPNET_MEMBERSHIP 
UserId  PK,FK 
ApplicationID FK NOT NULL 
other membership columns... 

這兩個表之間存在一對一的關係。我試圖在兩個表一起,地圖數據來自表連接到一個「用戶」的實體,看起來像這樣:

public class User 
{ 
    public virtual Guid Id { get; set; } 
    public virtual Guid ApplicationId { get; set; } 

    // other properties to be mapped from aspnetuser/membership tables ... 

我的映射文件如下:

public class UserMap : ClassMap<User> 
{ 
    public UserMap() 
    { 
     Table("aspnet_Users"); 
     Id(user => user.Id).Column("UserId").GeneratedBy.GuidComb(); 
     Map(user => user.ApplicationId); 
     // other user mappings 

     Join("aspnet_Membership", join => { 
      join.KeyColumn("UserId"); 
      join.Map(user => user.ApplicationId); 
      // Map other things from membership to 'User' class 
     } 
    } 
} 

如果我試着用上面的代碼運行我得到一個FluentConfiguration異常

試圖添加屬性'ApplicationId'時已添加。

如果我刪除了行「Map(user => user.ApplicationId);」或將其更改爲「地圖(用戶=> user.ApplicationId).Not.Update()Not.Insert();那麼應用程序運行,但我得到下面的異常試圖插入一個新用戶時:

不能將值NULL插入到'ApplicationId'列'ASPNETUsers_Dev.dbo.aspnet_Users'列中;列不允許有空值。 INSERT失敗。 該聲明已被終止。

如果我離開.MAP(用戶=> user.ApplicationId),因爲它原本是和做任何的這些變化對加入 .MAP(用戶=> user.ApplicationId)那麼我會得到上述相同的例外,當然除了例外與插入到aspnet_Membership表中有關

所以...我如何做這種映射假設我不能改變我的數據庫模式?

+0

如果我理解你的模式表,看起來你有一個由** userId和ApplicationId組成的組合鍵。嘗試定義組合鍵,然後使用該鍵進行連接映射。 – Tahbaza 2010-11-15 01:18:54

回答

4

我想我得到了一些有用的東西。

public class Application 
    { 
     public virtual Guid ApplicationId { get; set; } 


     /* Scalar Properties of an Application */ 
     public virtual string ApplicationName { get; set; } 
     public virtual string Description { get; set; } 

     public virtual string LoweredApplicationName 
     { 
      get 
      { 
       return this.ApplicationName.ToLower(); 
      } 
      set 
      { 
       if (String.IsNullOrEmpty(this.ApplicationName)) 
       { 
        this.ApplicationName = value; 
       } 
      } 
     } 

     public virtual IList<Membership> TheManyMemberships { get; protected set; } 

    } 


    public class User 
    { 
     public virtual Guid Id { get; set; } 
     public virtual Application TheApplication { get; set; } 

     public virtual Membership TheMembership { get; set; } 

     /* Scalar Properties of a User */ 
     public virtual string UserName { get; set; } 
    } 


    public class Membership 
    { 
     private Guid UserId { get; set; } 
     private User _theUser { get; set; } 

     protected Membership() { } 

     public Membership(User theUser) 
     { 
      _theUser = theUser; 
     } 

     public virtual Application TheApplication { get; set; } 

     /* Scalar Properties of a Membership */ 
     public virtual string Password { get; set; } 
} 





    public class ApplicationMap : ClassMap<Application> 
    { 
     public ApplicationMap() 
     { 
      Table("aspnet_Applications"); 
      Id(app => app.ApplicationId).Column("ApplicationId").GeneratedBy.GuidComb(); 
      Map(x => x.ApplicationName); 
      Map(x => x.LoweredApplicationName); 
      Map(x => x.Description); 

      HasMany<Membership>(x => x.TheManyMemberships) 
       .Inverse() 
       .AsBag(); 
     } 
    } 


    public class UserMap : ClassMap<User> 
    { 
     public UserMap() 
     { 
      Table("aspnet_Users"); 
      Id(user => user.Id).Column("UserId").GeneratedBy.GuidComb(); 
      References(x => x.TheApplication, "ApplicationId") 
        .Not.Nullable(); 

      HasOne(x => x.TheMembership) 
      .Cascade.All();// 
      //.Constrained(); 

      Map(x => x.UserName).Not.Nullable(); 

     } 
    } 


    public class MembershipMap : ClassMap<Membership> 
    { 
     public MembershipMap() 
     { 
      Table("aspnet_Membership"); 

      Id(Reveal.Member<Membership>("UserId")) 
       .GeneratedBy.Foreign("_theUser"); 
      HasOne(
       Reveal.Member<Membership, User>("_theUser")) 
        .Constrained() 
        .ForeignKey(); 

      References<Application>(x => x.TheApplication, "ApplicationId") 
      .Not.Nullable(); 

      Map(x => x.Password); 

     } 
    } 

原諒一些命名約定,當原型時,我使用非模糊名稱而不使用正確約定來避免混淆。

我有(從上面的代碼)和從asp.net(4.0)的輸出(使用aspnet_regsql.exe構建DDL)DDL似乎一致(兩個版本之間)的DDL。

我要感謝這個帖子: http://brunoreis.com/tech/fluent-nhibernate-hasone-how-implement-one-to-one-relationship/

如果你做任何調整,那麼請張貼。

但我能夠保存一個應用程序,用戶和會員資格。

但是,我想我可能會略微與用戶:會員關係。 微軟的方案似乎是「有一個用戶,但允許該用戶爲每個應用程序有不同的密碼」,這是有道理的。 但有時使用的MembershipProvider代碼(MS代碼,無關NHibernate的時候,我的「感覺」就像有時它假定一個單一的應用程序。

我覺得像MS DDL應該有 DBO的唯一約束。 。會員(用戶ID,的applicationID),但我沒有看到它在自己的DDL

無論如何,這應該深思提供一些食物

+0

+1使用不含糊的名字 – 2011-06-23 01:54:49

0

你嘗試繼承:

public class User 
.... 

public class Member : User 
.... 

你爲什麼加入ApplicationId的所有原因?我相信這是在兩個表中供參考。由於UserId是Guid,它是唯一的。如果您確實遇到需要爲兩個不同的應用程序存儲同一用戶的情況,那麼您無法通過asp.net成員資格不能這樣工作,它會創建兩個不同的用戶記錄。對用戶名/密碼的查找會根據Web應用程序設置(機器密鑰)檢查應用程序ID,以確保其唯一性。會員表是紅鯡魚。

+0

但是有時當使用MembershipProvider代碼時(MS代碼,與NHibernate無關,我覺得「有時候它假設有一個應用程序。」 – granadaCoder 2010-12-20 22:28:48

+0

// Quote //。If you do有你需要存儲兩個不同應用程序的同一用戶的情況,以及你不能這樣做的asp.net成員資格不工作,它會創建兩個不同的用戶記錄//最後引用我與你(BobTodd) 。它就像他們設置DDL與1個用戶一起工作,N個成員(每個應用程序有一個不同的密碼),但實際上,它不起作用,我認爲他們可能已經清理了4.0,但我沒有我認爲HasOne接近成員子類User,代碼明顯不同,但DDL明智的非常相似。 – granadaCoder 2010-12-20 22:35:07

相關問題