流畅的NHibernate使用子类关系自动继承 [英] Fluent NHibernate automap inheritance with subclass relationship

查看:242
本文介绍了流畅的NHibernate使用子类关系自动继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Fluent NHibernate自动化继承方面遇到了问题。下面是我的实体设置(简称为简称)。我已经将Fluent NHibernate配置为使用鉴别器列为层次结构创建1个类。自动化似乎正常工作,因为当我生成数据库时,创建一个名为AddressBase的表,其中一个标识符列表示每行的地址类型。

I am having an issue with using Fluent NHibernate automapping with Inheritance. Below is my entity setup (abbreviated for simplicity). I have configured Fluent NHibernate to create 1 class for the hierarchy with a discriminator column. The automapping appears to be working correctly as when I generate a database, one table is created named "AddressBase" with a discriminator column that signals what type of address each row is.

问题在于,当我在UserAccount类上调用方法GetPrimaryBillingAddress()而不是仅仅查询Billing Addresses时,NHibernate正在创建一个查询,查看结算和送货地址。它根本没有考虑到鉴别器。我假设我可以设置某种配置,但无法找到任何内容。

The problem lies in the face that when I call the method "GetPrimaryBillingAddress()" on the UserAccount class, instead of just querying Billing Addresses, NHibernate is creating a query that looks at both Billing and Shipping Addresses. It doesn't take into account the discriminator at all. I am assuming there is some sort of configuration I can set but have not been able to find anything.

public abstract class AddressBase : ActiveRecord<AddressBase>
{
    public virtual long Id { get; set; }

    public virtual string Address1 { get; set; }

}

public class AddressBilling : AddressBase
{
    public class TypedQuery : ActiveRecordQuery<AddressBilling> { }

    public virtual bool IsPrimary { get; set; }
}

public class AddressShipping : AddressBase
{
    public class TypedQuery : ActiveRecordQuery<AddressShipping> { }

    [Display(Name = "Is Primary")]
    public virtual bool IsPrimary { get; set; }

}

public class UserAccount : ActiveRecord<UserAccount>
{
    public virtual long Id { get; set; }

    public virtual IList<AddressBilling> BillingAddresses { get; set; }
    public virtual IList<AddressShipping> ShippingAddresses { get; set; }

    public UserAccount()
    {
        BillingAddresses = new List<AddressBilling>();
        ShippingAddresses = new List<AddressShipping>();
    }

    public virtual AddressBilling GetPrimaryBillingAddress()
    {
        if (BillingAddresses.Any(x => x.IsPrimary))
        {
            return BillingAddresses.Single(x => x.IsPrimary);
        }

        return BillingAddresses.FirstOrDefault();
    }

    public virtual AddressShipping GetPrimaryShippingAddress()
    {
        if (ShippingAddresses.Any(x => x.IsPrimary)) {
            return ShippingAddresses.Single(x => x.IsPrimary);            
        }

        return ShippingAddresses.FirstOrDefault();
    }

}

更新:
以下是自动化中使用的Mapping覆盖函数:

UPDATE: Here is the Mapping override functions used in the automapping:

private static FluentConfiguration GetFluentConfiguration(string connectionStringName = "CS")
{
        var autoMapping = AutoMap
            .AssemblyOf<Product>(new Mapping.AutoMappingConfiguration())
            .Conventions.Setup(c =>
            {
                c.Add<Mapping.ForeignKeyConvention>();
                c.Add<Mapping.DiscriminatorConvention>();
            })
            .IgnoreBase<AddressBilling.TypedQuery>()
            .IgnoreBase<AddressShipping.TypedQuery>()
            .IncludeBase<AddressBase>();

        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey(connectionStringName)))
            .Mappings(m => m.AutoMappings.Add(autoMapping));
}

public class AutoMappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        var isStatic = type.IsAbstract && type.IsSealed;

        return type.Namespace == typeof(Entities.Product).Namespace && !isStatic;
    }

    public override bool IsDiscriminated(Type type)
    {

        if (type == (typeof(Entities.AddressBase))) {
            return true;
        }

        return false;
    }

    public override string GetDiscriminatorColumn(Type type)
    {
        return "Type";
    }

public class DiscriminatorConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        //Address 
        if (instance.Name == typeof(AddressBilling).AssemblyQualifiedName)
        {
            instance.DiscriminatorValue(Enums.AddressType.BillingAddress);
        } 
        else if (instance.Name == typeof(AddressShipping).AssemblyQualifiedName)
        {
            instance.DiscriminatorValue(Enums.AddressType.ShippingAddress);
        }
    }
}

谢谢!

推荐答案

请尝试更改您的类UserAccount,如下所示:

Please, try to change your class UserAccount like this:

public class UserAccount : ActiveRecord<UserAccount>
{
    public virtual IList<AddressBase> Addresses { get; set; }
    public virtual IList<AddressBilling> BillingAddresses { get {return this.Addresses.OfType<AddressBilling>();} }
    public virtual IList<AddressShipping> ShippingAddresses { get {return this.Addresses.OfType<AddressShipping>();} }
    // ...
}

当然,这里只应映射地址属性。

Of course, only Addresses property should be mapped here.

这篇关于流畅的NHibernate使用子类关系自动继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆