问题描述
这和我以前的问题非常相似:
>说我有这些模型: public class Person
{
public virtual int Id {get;私人设置}
公共虚拟ICollection<地址>地址{get;私人设置}
}
public class Address
{
public virtual int Id {get;私人设置}
public virtual Person Owner {get;组; }
}
我想让FluentNHibernate创建下列表格:
$ $ p $ $ $ $
$ Person $
$ Address $ $ $ $ $ $ $ $ $ $ $ $ $ $'
使用流利的映射可以轻松实现:
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);
引用(x => x.Person).Column(OwnerId);
$ b我想通过使用自动映射得到相同的结果。我尝试了以下约定:
$ p $ 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));
}
}
//从@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 )
返回type.Name +Id;
返回property.Name +Id;
$ / code $ / pre
但是它创建了如下表格:
$ $ $ $ $ $ b $ Person $
$ Address $ $ $ $ $ $ $ $ $ $ b $ PersonId应该不存在
所以我加了一个AutoMappingOverride:
public class PersonMappingOverride:IAutoMappingOverride< Person>
{
public void Override(AutoMapping< Person> mapping)
{
mapping.HasMany(x => x.Addresses).KeyColumn(OwnerId);
$ b 这正确地解决了这个问题。但是我想用属性&惯例。我试过:
public class Person
{
public virtual int Id {get;私人设置}
[KeyColumn(OwnerId)]
public virtual ICollection< Address>地址{get;私人设置}
}
class KeyColumnAttribute:属性
{
public readonly string Name;
public KeyColumnAttribute(string name)
{
Name = name;
$ b $ 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);
但是它创建了这些表:
Person
PersonId
地址
AddressId
OwnerId
PersonId //这个列不应该存在
以下是我的其他代码:
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();
有什么想法?
$ p
测试项目可以从下载。 。
解决方案叹息...学习NHibernate真的是一个拉发的经验。
无论如何,我想我终于想出了如何解决这个问题:只要删除 SimpleForeignKeyConvention
,一切都会正常工作。
似乎 SimpleForeignKeyConvention
与 ReferenceKeyConvention
& ; KeyColumnConvention
。它的优先级高于 KeyColumnConvention
但优先级低于 ReferenceKeyConvention
。
ForeignKeyConvention
{
保护覆盖字符串GetKeyName(成员属性,类型类型)
{
if(property = = null)
//这行将禁用`KeyColumnConvention`
return type.Name +Id;
//当启用ReferenceKeyConvention时,此行不起作用。
返回property.Name +Id;
}
}
This is very similar to my previous question: FluentNHibernate: How to translate HasMany(x => x.Addresses).KeyColumn("PersonId") into automapping
Say I have these models:
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; }
}
I want FluentNHibernate to create the following tables:
Person
PersonId
Address
AddressId
OwnerId
This can be easily achieved by using fluent mapping:
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");
}
}
I want to get the same result by using auto mapping. I tried the following conventions:
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";
}
}
But it created the following tables:
Person
PersonId
Address
AddressId
OwnerId
PersonId // this column should not exist
So I added a AutoMappingOverride:
public class PersonMappingOverride : IAutoMappingOverride<Person>
{
public void Override(AutoMapping<Person> mapping)
{
mapping.HasMany(x => x.Addresses).KeyColumn("OwnerId");
}
}
This correctly solved the problem. But I want to get the same result using attribute & convention. I tried:
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);
}
}
}
But it created these tables:
Person
PersonId
Address
AddressId
OwnerId
PersonId // this column should not exist
Below is the rest of my code:
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();
Any ideas? Thanks.
Update:
The test project can be downloaded from here.
解决方案 Sigh... Learning NHibernate is really a hair pulling experience.
Anyway I think I finally figured out how to solve this problem: Just remove the SimpleForeignKeyConvention
and everything will work fine.
It seems the SimpleForeignKeyConvention
conflicts with both ReferenceKeyConvention
& KeyColumnConvention
. It has higher priority than KeyColumnConvention
but lower priority than 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";
}
}
这篇关于FluentNHibernate:使用属性和约定自动映射OneToMany关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!