У меня есть схема базы данных, где конвенция для имени внешнего ключа:
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, я рад принять тот ответ.
Если вы можете получить 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 );
}
)
Взгляните на соглашения и особенно на реализацию пользовательского соглашения по внешнему ключу.
ОБНОВЛЕНИЕ:
Вот пример. Предполагая следующий домен:
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();