6 nhibernate fluent-nhibernate automapping
这与我之前的问题非常类似:FluentNHibernate:如何将HasMany(x => x.Addresses).KeyColumn("PersonId")转换为自动化
说我有这些模型:
public class Person
{
public virtual int Id { get; private set; }
public virtual ICollection<Address> Addresses { get; private set; }
}
public class Address
{
public virtual int Id { get; private set; }
public virtual Person Owner { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我希望FluentNHibernate创建以下表:
Person
PersonId
Address
AddressId
OwnerId
Run Code Online (Sandbox Code Playgroud)
这可以通过使用流畅的映射轻松实现:
public class PersonMapping : ClassMap<Person>
{
public PersonMapping()
{
Id(x => x.Id).Column("PersonId");
HasMany(x => x.Addresses).KeyColumn("OwnerId");
}
}
public class AddressMapping : ClassMap<Address>
{
public AddressMapping()
{
Id(x => x.Id).Column("AddressId");
References(x => x.Person).Column("OwnerId");
}
}
Run Code Online (Sandbox Code Playgroud)
我想通过使用自动映射获得相同的结果.我尝试了以下约定:
class PrimaryKeyNameConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.Column(instance.EntityType.Name + "Id");
}
}
class ReferenceNameConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
instance.Column(string.Format("{0}Id", instance.Name));
}
}
// Copied from @Fourth: https://stackoverflow.com/questions/6091290/fluentnhibernate-how-to-translate-hasmanyx-x-addresses-keycolumnpersonid/6091307#6091307
public class SimpleForeignKeyConvention : ForeignKeyConvention
{
protected override string GetKeyName(Member property, Type type)
{
if(property == null)
return type.Name + "Id";
return property.Name + "Id";
}
}
Run Code Online (Sandbox Code Playgroud)
但它创建了以下表格:
Person
PersonId
Address
AddressId
OwnerId
PersonId // this column should not exist
Run Code Online (Sandbox Code Playgroud)
所以我添加了一个AutoMappingOverride:
public class PersonMappingOverride : IAutoMappingOverride<Person>
{
public void Override(AutoMapping<Person> mapping)
{
mapping.HasMany(x => x.Addresses).KeyColumn("OwnerId");
}
}
Run Code Online (Sandbox Code Playgroud)
这正确地解决了这个问题.但我希望使用属性和约定获得相同的结果.我试过了:
public class Person
{
public virtual int Id { get; private set; }
[KeyColumn("OwnerId")]
public virtual ICollection<Address> Addresses { get; private set; }
}
class KeyColumnAttribute : Attribute
{
public readonly string Name;
public KeyColumnAttribute(string name)
{
Name = name;
}
}
class KeyColumnConvention: IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
var keyColumnAttribute = (KeyColumnAttribute)Attribute.GetCustomAttribute(instance.Member, typeof(KeyColumnAttribute));
if (keyColumnAttribute != null)
{
instance.Key.Column(keyColumnAttribute.Name);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但它创建了这些表:
Person
PersonId
Address
AddressId
OwnerId
PersonId // this column should not exist
Run Code Online (Sandbox Code Playgroud)
以下是我的其余代码:
ISessionFactory sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
.Mappings(m =>
m.AutoMappings.Add(AutoMap.Assemblies(typeof(Person).Assembly)
.Conventions.Add(typeof(PrimaryKeyNameConvention))
.Conventions.Add(typeof(PrimaryKeyNameConvention))
.Conventions.Add(typeof(ReferenceNameConvention))
.Conventions.Add(typeof(SimpleForeignKeyConvention))
.Conventions.Add(typeof(KeyColumnConvention)))
//m.FluentMappings
// .Add(typeof (PersonMapping))
// .Add(typeof (AddressMapping))
)
.ExposeConfiguration(BuildSchema)
.BuildConfiguration()
.BuildSessionFactory();
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?谢谢.
更新:
测试项目可以从这里下载.
小智 7
叹息......学习NHibernate真的是一种拔毛的体验.
无论如何,我想我终于弄清楚如何解决这个问题:只需删除SimpleForeignKeyConvention,一切都会正常工作.
它似乎SimpleForeignKeyConvention与双方矛盾ReferenceKeyConvention及KeyColumnConvention.它具有比KeyColumnConvention优先级更高但优先级更低的优先级ReferenceKeyConvention.
public class SimpleForeignKeyConvention : ForeignKeyConvention
{
protected override string GetKeyName(Member property, Type type)
{
if(property == null)
// This line will disable `KeyColumnConvention`
return type.Name + "Id";
// This line has no effect when `ReferenceKeyConvention` is enabled.
return property.Name + "Id";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1996 次 |
| 最近记录: |