Question

Automap de Fluentnhibernate prend-il en charge la création d'une contrainte unique multi-colonnes via la convention?

Je peux facilement créer une seule colonne de contrainte unique:

public void Apply(IPropertyInstance instance)
{
    if(instance.Name.ToUpper().Equals("NAME"))
        instance.Unique();
}

Avec un critère d'acceptation pour trouver uniquement ReferenceEntity les types.

J'ai maintenant une entité que je souhaite créer une contrainte unique de plusieurs colonnes. Je prévoyais de décorer les propriétés de l'entité avec un attribut pour indiquer qu'ils font partie de la même clé unique, c'est-à-dire:

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; }
}

Et demandez à la convention de rechercher ces attributs et créez un unique dans tous les champs qui partagent la même clé unique.

La IProperyConvention L'interface vous permet de spécifier Unique sur l'instance spécifique (colonne) mais sans visibilité sur d'autres colonnes.

Mise à jour

Le processus de publication m'a aidé à réfléchir à un peu plus, alors j'ai écrit ceci:

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);
    }
}

En parcourant le code, il frappe le instance.UniqueKey(...) ligne deux fois (comme prévu), mais la contrainte créée (pgsql);

ADD CONSTRAINT foo_name_key UNIQUE(name);

Quand je m'attendais

ADD CONSTRAINT name_parent UNIQUE(name, bar);

MISE À JOUR 2

Lorsque vous utilisez le Override() Méthode dans la configuration automapale, je peux spécifier les touches uniques correctes:

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

Cela pourrait être un problème avec l'auto-mapper, pas sûr. Pas encore idéal car il n'est pas générique via une décoration d'attribut, mais pour l'instant, le dataModel reflète les exigences du domaine.

Était-ce utile?

La solution

Quand je l'ai fait, j'ai créé 2 conventions, l'une était une convention attributive-uperty et l'autre était une ireferencion convention. Mon attribut ressemblait à ceci:

public class UniqueAttribute : Attribute
{
    public UniqueAttribute(string uniqueKey)
    {
        UniqueKey = uniqueKey;
    }

    public string UniqueKey { get; set; }

    public string GetKey()
    {
        return string.Concat(UniqueKey, "Unique");
    }
}

Ma convention de propriété:

public class UniquePropertyConvention : AttributePropertyConvention<UniqueAttribute>
{
    protected override void Apply(UniqueAttribute attribute, IPropertyInstance instance)
    {
        instance.UniqueKey(attribute.GetKey());
    }
}

Et enfin la convention de référence:

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());
        }
    }
}

J'espère que cela fonctionne pour votre scénario.

Autres conseils

Ne le fais pas .... appliquer l'unicité dans votre domaine;)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top