FluentNHibernate:使用属性和约定自动映射OneToMany关系 [英] FluentNHibernate: Automapping OneToMany relation using attribute and convention

查看:106
本文介绍了FluentNHibernate:使用属性和约定自动映射OneToMany关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这和我以前的问题非常相似: FluentNHibernate:如何将HasMany(x => x.Addresses).KeyColumn(PersonId)转换为自动映射

>说我有这些模型:

  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关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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