FluentNHibernate的自动化是否支持通过约定创建多列唯一约束?
我可以轻松创建单列唯一约束:
public void Apply(IPropertyInstance instance)
{
if(instance.Name.ToUpper().Equals("NAME"))
instance.Unique();
}
使用验收标准仅查找ReferenceEntity
种类型。
我现在有一个实体,我想创建一个多列唯一约束。我正在计划用一个属性来装饰实体的属性,以表明它们构成了同一个唯一键的一部分,即:
public class Foo : Entity
{
[Unique("name_parent")]
public virtual string Name { get; set; }
public virtual string Description { get; set; }
[Unique("name_parent")]
public virtual Bar Parent { get; set; }
}
让约定查找这些属性,并在共享相同唯一键的所有字段中创建唯一属性。
IProperyConvention
界面允许您在特定实例(列)上指定Unique
,但不能查看其他列。
发布此过程的过程帮助我思考了一下,所以我写了这个:
var propertyInfo = ((PropertyInstance)(instance)).EntityType.GetMember(instance.Name).FirstOrDefault();
if (propertyInfo != null)
{
var attributes = propertyInfo.GetCustomAttributes(false);
var uniqueAttribute = attributes.OfType<UniqueAttribute>().FirstOrDefault();
if (uniqueAttribute != null)
{
instance.UniqueKey(uniqueAttribute.Key);
}
}
单步执行代码会按instance.UniqueKey(...)
行两次(按预期方式),但是创建的约束(pgsql);
ADD CONSTRAINT foo_name_key UNIQUE(name);
当我预料到的时候
ADD CONSTRAINT name_parent UNIQUE(name, bar);
在AutoMap配置中使用Override()
方法时,我可以指定正确的唯一键:
.Override<Foo>(map => {
map.Map(x => x.Name).UniqueKey("name_parent");
map.Map(x => x.Description);
map.References(x => x.Parent).UniqueKey("name_parent");
})
这可能是自动映射器的问题,不确定。不理想,因为它不是通过属性修饰的通用,但目前数据模型反映了域要求。
答案 0 :(得分:4)
当我这样做时,我创建了2个约定。一个是AttributePropertyConvention,另一个是IReferenceConvention。我的属性看起来像这样:
public class UniqueAttribute : Attribute
{
public UniqueAttribute(string uniqueKey)
{
UniqueKey = uniqueKey;
}
public string UniqueKey { get; set; }
public string GetKey()
{
return string.Concat(UniqueKey, "Unique");
}
}
我的财产惯例:
public class UniquePropertyConvention : AttributePropertyConvention<UniqueAttribute>
{
protected override void Apply(UniqueAttribute attribute, IPropertyInstance instance)
{
instance.UniqueKey(attribute.GetKey());
}
}
最后是参考惯例:
public class UniqueReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
var p = instance.Property.MemberInfo;
if (Attribute.IsDefined(p, typeof(UniqueAttribute)))
{
var attribute = (UniqueAttribute[])p.GetCustomAttributes(typeof(UniqueAttribute), true);
instance.UniqueKey(attribute[0].GetKey());
}
}
}
希望这适用于您的场景。
答案 1 :(得分:1)
不要这样做......在你的域中强制执行唯一性;)