具有子类关系的Fluent NHibernate自动映射继承
我在使用Fluent NHibernate自动映射继承时遇到问题。下面是我的实体设置(为简单起见缩写)。我已将Fluent NHibernate配置为使用鉴别器列为层次结构创建1个类。自动映射似乎工作正常,就像我生成数据库时一样,创建了一个名为“AddressBase”的表,其中包含一个鉴别器列,指示每行的地址类型 问题在于,当我在UserAccount类上调用方法“GetPrimaryBillingAddress()”时,NHibernate正在创建一个查询,该查询同时查看帐单地址和发货地址,而不仅仅是查询帐单地址。它根本不考虑鉴别器。我假设有某种配置我可以设置,但没有找到任何东西具有子类关系的Fluent NHibernate自动映射继承,nhibernate,inheritance,relationship,fluent,automapping,Nhibernate,Inheritance,Relationship,Fluent,Automapping,我在使用Fluent NHibernate自动映射继承时遇到问题。下面是我的实体设置(为简单起见缩写)。我已将Fluent NHibernate配置为使用鉴别器列为层次结构创建1个类。自动映射似乎工作正常,就像我生成数据库时一样,创建了一个名为“AddressBase”的表,其中包含一个鉴别器列,指示每行的地址类型 问题在于,当我在UserAccount类上调用方法“GetPrimaryBillingAddress()”时,NHibernate正在创建一个查询,该查询同时查看帐单地址和发货地址,
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();
}
}
公共抽象类AddressBase:ActiveRecord
{
公共虚拟长Id{get;set;}
公共虚拟字符串地址1{get;set;}
}
公共类AddressBilling:AddressBase
{
公共类TypedQuery:ActiveRecordQuery{}
公共虚拟bool IsPrimary{get;set;}
}
公共类AddressShipping:AddressBase
{
公共类TypedQuery:ActiveRecordQuery{}
[显示(Name=“Is Primary”)]
公共虚拟bool IsPrimary{get;set;}
}
公共类用户帐户:ActiveRecord
{
公共虚拟长Id{get;set;}
公共虚拟IList计费地址{get;set;}
公共虚拟IList ShippingAddresses{get;set;}
公共用户帐户()
{
BillingAddresses=新列表();
ShippingAddresses=新列表();
}
公共虚拟地址计费GetPrimaryBillingAddress()
{
if(账单地址任意(x=>x.IsPrimary))
{
返回BillingAddresss.Single(x=>x.IsPrimary);
}
返回BillingAddresss.FirstOrDefault();
}
公共虚拟地址Shipping GetPrimaryShippingAddress()
{
if(发货地址任意(x=>x.IsPrimary)){
返回ShippingAddresses.Single(x=>x.IsPrimary);
}
返回ShippingAddresses.FirstOrDefault();
}
}
更新:
以下是自动映射中使用的映射覆盖函数:
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);
}
}
}
private static FluentConfiguration GetFluentConfiguration(string connectionStringName=“CS”)
{
var自动映射=自动映射
.AssemblyOf(新映射.AutoMappingConfiguration())
.Conventions.Setup(c=>
{
c、 添加();
c、 添加();
})
.IgnoreBase()
.IgnoreBase()
.IncludeBase();
流畅地返回。Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(c=>c.FromConnectionStringWithKey(connectionStringName)))
.Mappings(m=>m.AutoMappings.Add(autoMapping));
}
公共类自动映射配置:默认自动映射配置
{
公共覆盖布尔ShouldMap(类型)
{
var isStatic=type.isastract&&type.IsSealed;
返回type.Namespace==typeof(Entities.Product).Namespace&&!isStatic;
}
公共覆盖布尔值已区分(类型)
{
if(type==(typeof(Entities.AddressBase))){
返回true;
}
返回false;
}
公共重写字符串GetDiscriminatorColumn(类型)
{
返回“类型”;
}
公共类鉴别器约定:ISubclassConvention
{
public void Apply(ISubclassInstance实例)
{
//地址
if(instance.Name==typeof(AddressBilling.AssemblyQualifiedName)
{
DiscriminatorValue(Enums.AddressType.BillingAddress);
}
else if(instance.Name==typeof(AddressShipping.AssemblyQualifiedName)
{
DiscriminatorValue(Enums.AddressType.ShippingAddress);
}
}
}
谢谢!请尝试如下更改您的类用户帐户:
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>();} }
// ...
}
公共类用户帐户:ActiveRecord
{
公共虚拟IList地址{get;set;}
公共虚拟IList BillingAddresses{get{返回this.Addresses.OfType();}
公共虚拟IList ShippingAddresses{get{返回this.Addresses.OfType();}
// ...
}
当然,这里应该只映射Addresses属性。如何映射用户帐户的属性BillingAddresses和ShippingAddresses?是否有一些映射覆盖?更新后的帖子包括映射覆盖。