简体   繁体   English

nHibernate中的子类表映射

[英]Subclass table mapping in nHibernate

Firstly, sorry about the wall of text. 首先,对文本墙感到抱歉。

I have the following schema. 我有以下架构。 Note that User_Contact may contain a null in ContactID . 请注意, User_Contact ContactID可以包含null。

架构图

At the class level it is then implemented in the following way 然后在类级别上以以下方式实现

public abstract class User : EntityBase<Guid>, IAggregateRoot
{
    public User()
    {

    }

    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }

    protected abstract override void Validate();
}

public class SiteUser : User
{
    public SiteUser() { }

    public virtual Guid ApplicationId { get; set; }
    public virtual string UserName { get; set; }
    public virtual string LoweredUserName { get; set; }
    public virtual string MobileAlias { get; set; }
    public virtual bool IsAnonymous { get; set; }
    public virtual DateTime LastActivityDate { get; set; }

    protected override void Validate()
    { 
        if (this.ApplicationId == Guid.Empty)
            base.AddBrokenRule(UserBusinessRules.ApplicationIdRequired);

        if (this.UserName.IsNullOrEmpty())
            base.AddBrokenRule(UserBusinessRules.UserNameRequired);

        if (this.LoweredUserName.IsNullOrEmpty())
            base.AddBrokenRule(UserBusinessRules.LoweredUserNameRequired);

        if (this.LastActivityDate == DateTime.MinValue)
            base.AddBrokenRule(UserBusinessRules.LastActivityDateRequired);

    }
}

public class SiteContact : SiteUser
{

    public SiteContact() 
    {
    }


    public virtual int ExternalID { get; set; }
    //All the rest...

    protected override void Validate()
    { 
        //validate
    }
}

So basically the idea is that every single SiteContact is a SiteUser but not every SiteUser is a SiteContact . 因此,基本上的想法是,每个单独的SiteContact都是一个SiteUser但不是每个SiteUser都是一个SiteContact

Where I have gotten completely stuck is how on earth to map this relationship in nHibernate. 我完全陷入困境的是如何在nHibernate中映射这种关系。 I seem to be able to retrieve a SiteUser but unable to retrieve a SiteContact and it is clear why. 我似乎能够检索到SiteUser但无法检索到SiteContact ,这很清楚。 The mapping that I have implemented results in the following sql being executed. 我实现的映射导致执行以下sql。

SELECT this_.userid             AS UserId18_0_, 
       this_.firstname          AS FirstName18_0_, 
       this_.lastname           AS LastName18_0_, 
       //Blah blah.....
FROM   user_contact this_ 
       INNER JOIN contact this_1_ 
               ON this_.userid = this_1_.contactid  //Here is the error this should be ContactID = ContactID
       INNER JOIN aspnet_users this_2_ 
               ON this_.userid = this_2_.userid 
WHERE  ( CASE 
           WHEN this_.contactid IS NOT NULL THEN 1 
           ELSE 0 
         END ) = '1' 

But I can't for the life of me work out how to fix this problem in my hbm mapping file. 但是我无法终生解决如何在hbm映射文件中解决此问题。 Here is the file with some fields omitted for simplicity. 为了简单起见,这里是省略了一些字段的文件。

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="MyProject.Namespaces.Model.Entities" assembly="MyProject.Namespaces.Model">


  <class name="User" table="User_Contact" lazy="true" abstract="true">

    <id name="ID" column="UserId" type="guid">
      <generator class="guid" />
    </id>

    <discriminator column="ContactID" formula="(CASE WHEN ContactID IS NOT NULL THEN 1 ELSE 0 END)" />

    <property name="FirstName">
      <column name="FirstName" sql-type="nvarchar(500)" not-null="true" />
    </property>

    <property name="LastName">
      <column name="LastName" sql-type="nvarchar(500)" not-null="true" />
    </property>

    <subclass name="SiteContact" discriminator-value="1">
      <join table="Contact">
        <key column="ContactID" /> //I assume the problem is here. I have tried adding foreign-key="ContactID" to no success

        <property name="ExternalID" insert="false" update="false">
          <column name="ExternalID" sql-type="int" not-null="true" />
        </property>

        //The rest of the mapped columns

      </join>
      <join table="aspnet_Users">
        <key column="UserId" />

        <property name="ApplicationId">
          <column name="ApplicationId" sql-type="guid" not-null="true" />
        </property>

        <property name="UserName">
          <column name="UserName" sql-type="nvarchar(256)" not-null="true" />
        </property>

        <property name="LoweredUserName">
          <column name="LoweredUserName" sql-type="nvarchar(256)" not-null="true" />
        </property>

        <property name="MobileAlias">
          <column name="MobileAlias" sql-type="nvarchar(16)" not-null="false" />
        </property>

        <property name="IsAnonymous">
          <column name="IsAnonymous" sql-type="bit" not-null="true" />
        </property>

        <property name="LastActivityDate">
          <column name="LastActivityDate" sql-type="datetime" not-null="true" />
        </property>

      </join>
    </subclass>

    <subclass name="SiteUser" discriminator-value="0">
      <join table="aspnet_Users">
        <key column="UserId" />

        //blah blah blah

      </join>
    </subclass>

  </class>

</hibernate-mapping>

Hopefully someone could please tell me if I am even on the right track about this mapping and perhaps provide some guidance? 希望有人可以告诉我我是否在有关此映射的正确方法上,也许能提供一些指导?

This seems like a pretty convoluted way of mapping it. 这似乎是一种相当复杂的映射方式。 I'm not sure what benefits you're hoping to achieve from using inheritence in this situation, and I would suggest using composition instead (ie. having a class per table and mapping the relationships). 我不确定在这种情况下使用继承会带来什么好处,我建议改用合成(即每个表都有一个类并映射关系)。

Having said that, you presumably have your reasons, so I would suggest the following to achieve what I think you want: 话虽这么说,您大概有自己的理由,所以我建议采取以下措施来实现我认为的目标:

  1. Map your SiteUser class as the base class and use a join from User_Contact to aspnet_Users (so don't have User as the base in the mapping) 将您的SiteUser类映射为基类,并使用从User_Contact到aspnet_Users的联接(因此,在映射中不要将User作为基类)
  2. Map your SiteContact then as a subclass using the joined-subclass mapping instead of the subclass so you don't need to use discriminators. 然后,使用joined-subclass映射而不是子类将您的SiteContact映射为子类,因此您无需使用区分符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM