簡體   English   中英

Fluent NHibernate - 如何映射兩個連接表中存在的不可為空的外鍵

[英]Fluent NHibernate - How to map a non nullable foreign key that exists in two joined tables

我正在使用Fluent NHibernate為我的應用程序映射一組成員資格類。 我正在將類映射到asp.net成員資格數據庫結構。 與問題相關的數據庫模式如下所示:

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);”行 或者將其更改為“Map(user => user.ApplicationId) .Not.Update()。Not.Insert();然后應用程序運行,但在嘗試插入新用戶時出現以下異常:

無法將值NULL插入列'ApplicationId',表'ASPNETUsers_Dev.dbo.aspnet_Users'; 列不允許空值。 INSERT失敗。 該語句已終止。

如果我按原樣離開.Map(user => user.ApplicationId)並對連接 .Map(user => user.ApplicationId)進行其中任何一項更改,那么我會得到同樣的異常,當然除了異常與插入aspnet_Membership表有關

那么......假設我無法更改數據庫架構,我該怎么做這種映射?

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

  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);

        }
    }

原諒一些命名約定,在原型設計時,我使用不明確的名稱而不是正確的約定來避免混淆。

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

我要感謝這篇文章: http//brunoreis.com/tech/fluent-nhibernate-hasone-how-implement-one-to-one-relationship/

如果您進行任何調整,請發布它們。

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

但是,我認為我可能會略微偏離用戶:會員關系。 微軟的場景似乎是“擁有一個用戶,但允許該用戶為每個應用程序設置不同的密碼”,這是有道理的。 但有時當使用MembershipProvider代碼(MS代碼,與NHibernate無關)時,我“感覺”有時會假設一個應用程序。

我覺得MS DDL應該對dbo.Membership(UserId,ApplicationId)有一個獨特的約束,但我沒有在他們的DDL中看到它。

無論如何,這應該提供一些思考的食物。

你嘗試繼承了嗎?

public class User
....

public class Member : User
....

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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