Domanda

Automap di FluentNhibernate supporta la creazione di un vincolo unico multi-colonna tramite Convenzione?

Posso facilmente creare un vincolo univoco a colonna singola:

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

Con un criterio di accettazione da trovare solo ReferenceEntity tipi.

Ora ho un'entità che voglio creare un vincolo univoco multiplo. Avevo intenzione di decorare le proprietà dell'entità con un attributo per indicare che facevano parte della stessa chiave unica, cioè:

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

E fai cercare sulla convenzione questi attributi e crea un unico in tutti i campi che condividono la stessa chiave unica.

Il IProperyConvention L'interfaccia consente di specificare Unique sull'istanza specifica (colonna) ma senza visibilità su altre colonne.

Aggiornare

Il processo di pubblicazione di questo mi ha aiutato a pensare un po 'di più, quindi ho scritto questo:

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

Passando il codice colpisce il instance.UniqueKey(...) riga due volte (come previsto), tuttavia il vincolo creato (PGSQL);

ADD CONSTRAINT foo_name_key UNIQUE(name);

Quando mi sarei aspettato

ADD CONSTRAINT name_parent UNIQUE(name, bar);

Aggiornamento 2

Quando si utilizza il Override() Metodo nella configurazione automatica, posso specificare i tasti univoci corretti:

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

Questo potrebbe essere un problema con l'auto-mapper, non sono sicuro. Non è ancora l'ideale in quanto non è generico tramite la decorazione di attributi, ma per ora il datamodel riflette i requisiti di dominio.

È stato utile?

Soluzione

Quando l'ho fatto ho creato 2 convegni una era un attributoPropertyConvenzione e l'altro era un IreferenceConvenzione. Il mio attributo sembrava così:

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

    public string UniqueKey { get; set; }

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

Convenzione della mia proprietà:

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

E infine la convenzione di riferimento:

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

Spero che funzioni per il tuo scenario.

Altri suggerimenti

Non farlo .... imporre unicità nel tuo dominio;)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top