3

FluentNHibernate の automap は、規則による複数列の一意の制約の作成をサポートしていますか?

単一の列の一意の制約を簡単に作成できます。

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(...)(予想どおり) 行に 2 回ヒットしますが、制約が作成されます (pgsql)。

ADD CONSTRAINT foo_name_key UNIQUE(name);

私が期待していたとき

ADD CONSTRAINT name_parent UNIQUE(name, bar);

更新 2

Override()AutoMap 構成でメソッドを使用すると、正しい一意のキーを指定できます。

.Override<Foo>(map => {
    map.Map(x => x.Name).UniqueKey("name_parent");
    map.Map(x => x.Description);
    map.References(x => x.Parent).UniqueKey("name_parent");
})

これは自動マッパーの問題かもしれませんが、よくわかりません。属性の装飾を介して一般的ではないため、まだ理想的ではありませんが、今のところ、データモデルはドメインの要件を反映しています。

4

2 に答える 2

4

これを行ったときに、2 つの規則を作成しました。1 つは AttributePropertyConvention で、もう 1 つは 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());
        }
    }
}

うまくいけば、これはあなたのシナリオでうまくいきます。

于 2011-05-12T14:16:16.460 に答える
1

しないでください....ドメインに一意性を強制します;)

于 2011-05-13T06:24:37.620 に答える