Я могу сделать Быструю конвенцию внешнего ключа NHibernate, которая включает родительское ключевое имя?

У меня есть схема базы данных, где конвенция для имени внешнего ключа:

ForeignTable.Name + ForeignTable.PrimaryKeyName

Так, для a Child таблица, ссылающаяся a Parent таблица с названным столбцом первичного ключа Key, внешний ключ будет похож ParentKey.

Существует ли способ создать эту конвенцию в моем Быстром отображении NHibernate?

В настоящее время я использую a 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";
    }
}

Это работает точно, как я хочу для всех типов, которые имеют "идентификатор" как первичный ключ. То, что я хотел бы сделать, заменить постоянный "идентификатор" названием первичного ключа ссылаемого типа.

Если это не в настоящее время возможно с Быстрым NHibernate, я рад принять тот ответ.

9
задан Paul Turner 26 February 2010 в 20:51
поделиться

2 ответа

Если вы можете получить Mapping для класса, вы можете получить имя его столбца 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;
    }
}

Мы можем получить объект Mapping, приложив немного усилий.

Конструкторы ClassMap могут передавать this в нашу коллекцию Mappers.

Для AutoMapping мы можем использовать Override следующим образом.

.Mappings( m => m.AutoMappings.Add( AutoMap.AssemblyOf<FOO>()
    .Override<User>( u => {
        u.Id( x => x.Id ).Column( "UID" );
        MyForeignKeyConvention.Mappings.Add( u );
    }
)
3
ответ дан 4 December 2019 в 20:23
поделиться

Взгляните на соглашения и особенно на реализацию пользовательского соглашения по внешнему ключу.


ОБНОВЛЕНИЕ:

Вот пример. Предполагая следующий домен:

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

public class Child
{
    public virtual string Id { get; set; }
    public virtual Parent Parent { get; set; }
}

, который необходимо сопоставить с этой схемой:

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

create table Parent(
    Id integer primary key
)

, вы можете использовать это соглашение:

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

и создать фабрику сеансов:

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();
7
ответ дан 4 December 2019 в 20:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: