我可以制作包含父键名称的Fluent NHibernate外键约定吗?

Pau*_*ner 9 naming-conventions fluent-nhibernate

我有一个数据库模式,其中外键名称的约定是:

ForeignTable.Name + ForeignTable.PrimaryKeyName
Run Code Online (Sandbox Code Playgroud)

因此,对于Child引用Parent具有名为主键列的表的表Key,外键将如下所示ParentKey.

有没有办法在我的Fluent NHibernate映射中创建这个约定?

目前我正在使用这样的ForeignKeyConvention实现:

public class ForeignKeyNamingConvention : ForeignKeyConvention
{
    protected override string GetKeyName(PropertyInfo property, Type type)
    {
        if (property == null)
        {
            // Relationship is many-to-many, one-to-many or join.
            if (type == null)
                throw new ArgumentNullException("type");

            return type.Name + "ID";
        }

        // Relationship is many-to-one.
        return property.Name + "ID";
    }
}
Run Code Online (Sandbox Code Playgroud)

对于所有以"ID"为主键的类型,这完全符合我的要求.我想要做的是将常量"ID"替换为所引用类型的主键的名称.

如果使用Fluent NHibernate目前无法做到这一点,我很乐意接受这个答案.

Dar*_*rov 7

查看约定,特别是实现自定义外键约定.


更新:

这是一个例子.假设以下域:

public class Parent
{
    public virtual int Id { get; set; }
}

public class Child
{
    public virtual string Id { get; set; }
    public virtual Parent Parent { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

需要映射到此架构:

create table Child(
    Id integer primary key, 
    ParentId integer
)

create table Parent(
    Id integer primary key
)
Run Code Online (Sandbox Code Playgroud)

你可以使用这个约定:

public class CustomForeignKeyConvention : IReferenceConvention
{
    public void Apply(IManyToOneInstance instance)
    {
        instance.Column(instance.Class.Name + "Id");
    }
}
Run Code Online (Sandbox Code Playgroud)

并创建会话工厂:

var sf = Fluently
    .Configure()
    .Database(
        SQLiteConfiguration.Standard.UsingFile("data.db3").ShowSql()
    )
    .Mappings(
        m => m.AutoMappings.Add(AutoMap
            .AssemblyOf<Parent>()
            .Where(t => t.Namespace == "Entities")
            .Conventions.Add<CustomForeignKeyConvention>()
        )
    )
    .BuildSessionFactory();
Run Code Online (Sandbox Code Playgroud)

  • 没有PrimaryKeyName这样的概念.这都是关于惯例的.按照惯例,所有主键列都应称为"Id".您可以通过为给定类型或所有类型实现"IIdConvention"来更改此默认行为,这意味着您已经知道此默认行为已更改的类型.因此,在"IReferenceConvention"中,根据类型,您可以应用正确的后缀. (2认同)

Lac*_*che 3

如果您可以获得Mapping<T>某个类的 ,则可以获得其 Id 列的名称。

public class MyForeignKeyConvention: ForeignKeyConvention
{
    public static IList<IMappingProvider> Mappings = new List<IMappingProvider>();

    protected override string GetKeyName( System.Reflection.PropertyInfo property, Type type )
    {
        var pk = "Id";

        var model = new PersistenceModel();
        foreach( var map in Mappings ) {
            model.Add( map );
        }

        try {
            var mymodel = (IdMapping) model.BuildMappings()
                .First( x => x.Classes.FirstOrDefault( c => c.Type == type ) != null )
                .Classes.First().Id;

            Func<IdMapping, string> getname = x => x.Columns.First().Name;
            pk = getname( mymodel );
        } catch {
        }

        if (property == null) {
            return type.Name + pk;
        }
        return type.Name + property.Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以通过一些管道来获取 Mapping 对象。

的构造函数ClassMap<T>可以传递this到我们的映射器集合中。

对于AutoMapping<T>,我们可以按如下方式使用 Override 。

.Mappings( m => m.AutoMappings.Add( AutoMap.AssemblyOf<FOO>()
    .Override<User>( u => {
        u.Id( x => x.Id ).Column( "UID" );
        MyForeignKeyConvention.Mappings.Add( u );
    }
)
Run Code Online (Sandbox Code Playgroud)