假设我有以下两个类:
public class User : Entity
{
public virtual IList<Item> Items { get; set; }
}
public class Item : Entity
{
public virtual User Owner { get; set; }
}
我创建了两个映射类:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id);
HasMany(x => x.Items);
}
}
public class ItemMap : ClassMap<Item>
{
public ItemMap()
{
Id(x => x.Id);
References(x => x.Owner);
}
}
这将生成一个包含Item
列和UserId
列的表OwnerId
。当我在KeyColumn("OwnerId")
映射上使用HasMany
时,它仅适用于OwnerId
列,但我希望避免这种情况。有没有办法告诉NHibernate,使用ItemMap
中的映射创建的列?
为什么我要避免明确指定列:
根据属性的名称和一些规则自动生成列名OwnerId
。如果我更改规则或属性名称,我还需要记住更改KeyColumn
。所以,基本上,它不是重构保存。
答案 0 :(得分:2)
更新:已修复错误
如果您在地图中应用规则,那么
public static void KeyColumnFromReference<TChild>(
this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map, Expression<Func<TChild, object>> referenceprop)
{
string propertyname = GetPropertyName(referenceprop);
var column = ((IMappingProvider)map).GetClassMapping()
.References.First(m => m.Name == propertyname)
.Columns.First().Name;
collectionmap.KeyColumn(column);
}
public static void KeyColumnFromReference<T, TChild>(
this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map)
{
var column = ((IMappingProvider)map).GetClassMapping()
.References.First(m => m.Type == typeof(TChild))
.Columns.First().Name;
collectionmap.KeyColumn(column);
}
public UserMap()
{
HasMany(x => x.Items)
.KeyColumnFromReference<User, Item>(new ItemMap());
// or
HasMany(x => x.Items)
.KeyColumnFromReference(new ItemMap(), u => u.Owner);
}
如果您将规则应用为约定,那么您需要实现IHasManyConvention
并对EntityType
和属性名(您必须通过ChildType反射获得)应用相同的规则
更新
class ForeignKeyConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
// to force the compiler to take the Name property and not the Name method
string propertyName = ((ICollectionInspector)instance).Name;
// should be equal to the convention for the reference key column
instance.Key.Column(propertyName + instance.EntityType.Name + "id");
}
}