Fluent NHibernate Collection Table-Per-Subclass

会有一股神秘感。 提交于 2019-12-14 03:48:02

问题


I am having trouble with inheritance in Fluent NHibernate.

I have managed to get Table-Per-Subclass working before but I can't get a collection of the baseclass to work. It is looking for a table for the base class which I don't have.

Here's my schema:

User(Id, Name, Email)

User_Account_Password(Id, UserId, PasswordHash, Salt)

User_Account_Facebook(Id, UserId, FacebookId)

Here's my object model:

public class User
{
  public virtual int Id { get; set; }
  public virtual string Name { get; set; }
  public virtual string Email { get; set; }
  public virtual IList<UserAccount> Accounts { get; set; }
}

public abstract class UserAccount
{
  public virtual int Id { get; set; }
  public virtual User User { get; set; }
}

public class UserAccountPassword : UserAccount
{
  public virtual string PasswordHash { get; set; }
  public virtual string Salt { get; set; }
}

public class UserAccountFacebook : UserAccount
{
  public virtual long FacebookId { get; set; }
}

Here's the mapping files:

public class UserMap : ClassMap<User>
{
   public UserMap()
   {
      Table("user");

      Id(x=>x.Id);

      Map(x=>x.Name);
      Map(x=>x.Email);

      //This is the collection I am having trouble with.
      HasMany(x=>x.Accounts)
       .KeyColumn("UserId")
       .Cascade.SaveUpdate()
       .Not.LazyLoad();
   }
}

public class UserAccountMap : ClassMap<UserAccount>
{
    public UserAccountMap()
    {
       Id(x=>x.Id);

       References(x => x.User)
          .Column("UserId");
    }
}

public class UserAccountPasswordMap : SubclassMap<UserAccountPassword>
{
    public UserAccountPasswordMap()
    {
        Table("user_account_password");

        Map(x=>x.PasswordHash);
        Map(x=>x.Salt);
    }
}

public class UserAccountFacebookMap : SubclassMap<UserAccountFacebook>
{
    public UserAccountFacebookMap()
    {
         Table("user_account_facebook");

         Map(x=>x.FacebookId);
    }
}

This would work fine if I had on user a collection of Facebook accounts and a collection of password accounts. However, the idea is to make these link to the user so that we can later allow people to not use facebook or to add facebook as a login method but to keep the same account.

The error I'm getting is "Table myschema.useraccount" does not exist. Which suggests it is ignoring the fact UserAccount is abstract..

This seems to be the recommended way to do Table-Per-Subclass according to http://wiki.fluentnhibernate.org/Fluent_mapping#Subclasses but it feels like I'm missing something.

Any ideas?


回答1:


Table-per-subclass is anti-intuitive name because a table is required for the base class (or super class) as well (see NH documentation). If the useraccount table does not exist, NH throws exception as in your case.

If you work with legacy database and a base class table is not available, then you could use table-per-concrete-class or so called union-subclass mapping:

public class UserAccountMap : ClassMap<UserAccount>
{
    public UserAccountMap()
    {
        Id(x => x.Id).GeneratedBy.Assigned(); // cannot use identity generator with union-subclass mapping

        References(x => x.User)
           .Column("UserId");

        this.UseUnionSubclassForInheritanceMapping(); // tell FNH that you are using table per concrete class mapping
    }
}

EDIT: UserAccount table must be present in database schema to use table-per-subclass mapping. The table must contain two columns: Id and UserId.



来源:https://stackoverflow.com/questions/5993200/fluent-nhibernate-collection-table-per-subclass

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!