Frage

Wenn Sie jemals einen String-Wert in fließend NHibernate setzen es alwasy die DB vales zu Nvarchar setzt (255), ich brauche eine ganz speichern viele lange Zeichenkette, die auf Benutzereingaben basieren und 255 ist nicht praktikabel.

Just hinzuzufügen dies ist ein Problem mit dem AutoMapper wie ich fließend NHibernate bin mit der Datenbank zu erstellen.

War es hilfreich?

Lösung

Mit dieser Konvention Hinzufügen wird die Standardlänge für String-Eigenschaften auf 10000. gesetzt Wie andere erwähnt haben, wird dies ein nvarchar sein (max) Spalte.

public class StringColumnLengthConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof(string)).Expect(x => x.Length == 0);
    }
    public void Apply(IPropertyInstance instance)
    {
        instance.Length(10000);
    }
}

können Konventionen auf eine Automap Konfiguration wie folgt hinzugefügt werden:

Fluently.Configure()
    .Mappings( m =>
        m.AutoMappings.Add( AutoMap.AssemblyOf<Foo>()
        .Conventions.Add<StringColumnLengthConvention >()))

Weitere Informationen finden Sie unter Konventionen in der Fluent NHibernate Wiki .

Andere Tipps

Zur Einstellung der Länge auf etwas über 4001 wird eine NVARCHAR (MAX) ...

erzeugen
.WithLengthOf(10000);

Sehen Sie hier für mehr Details ...

http://serialseb.blogspot.com/2009/ 01 / fließend-nhibernate-and-nvarcharmax.html

Mit Fluent NHibernate AutoMapper, man erkennt schnell, dass das Out-of-the-Box-Verhalten für varchar-Spalt ist weniger als ideal. Zuerst entdecken Sie, dass jeder String-Eigenschaft wurde als varchar exportiert (255), und Sie müssen eine Spalte machen varchar (max) zu sein. Aber im Idealfall würden Sie nicht jede Zeichenfolge ein varchar (max) machen müssen, nicht wahr? So fahren Sie nach unten, dass gut ausgetretenen Pfad, der beste Weg zu üben Kontrolle über den Prozess des Findens ohne ... im Spiel der verschiedenen eleganten Mustern auszubrechen

Wenn Sie Ihre resultierende Datenbank varchar-Spalten in unterschiedlichen Längen angegeben haben mögen, schauen Sie auf Konvention Klassen es geschehen zu lassen. Sie könnten versuchen, namentliche Bedingungen erstellen oder im Allgemeinen ein Namensmuster verwenden, die Sie in Ihrer Konvention Klasse erkannt.

ist weder ideal. einen Namen für den Zweck überlastet in einem anderen Teil des Codes ein beabsichtigtes spec der Angabe ist unfortunate- Ihr Name nur ein Name sein sollte. Ebenso wenig sollten Sie Konvention Code müssen jedes Mal, die Sie ändern hinzufügen oder eine begrenzte Länge Klasse Eigenschaft zu ändern. Wie können Sie also eine Konvention Klasse schreiben, die Ihnen die Kontrolle steuern und bietet eine einfache und elegante Art und Weise gibt?

Es wäre süß, wenn Sie könnten nur deco Ihr Eigentum, wie ich für die Body-Eigenschaft hat sich hier:

using System; 
using MyDomain.DBDecorations;

namespace MyDomain.Entities {
    [Serializable]
    public class Message
    {
        public virtual string MessageId { get; set; }

        [StringLength(4000)] public virtual string Body { get; set; }
    }
}

Wenn dies funktionieren könnte, würden wir die Kontrolle über jede Saite unabhängig haben, und wir würden in der Lage, es zu spezifizieren direkt in unserer Einheit.

Bevor ich einen Mahlstrom über Trennung von Datenbank-Anwendung starten, lassen Sie mich darauf hinweisen, dass dies nicht ausdrücklich eine Datenbank-Richtlinie (Ich habe einen Punkt nicht das Attribut ‚Varchar‘ aufrufen). Ich ziehe dies als eine Erweiterung des System.string zu charakterisieren und in meiner eigenen kleinen Universum ist ich zufrieden. Unterm Strich möchte ich eine Bequemlichkeit!

Um dies zu tun, müssen wir die Dekoration wir verwenden möchten, um definieren:

using System;
namespace MyDomain.DBDecorations
{

    [AttributeUsage(AttributeTargets.Property)]
    public class StringLength : System.Attribute
    {
        public int Length = 0;
        public StringLength(int taggedStrLength)
        {
            Length = taggedStrLength;
        }
    }
}

Schließlich brauchen wir eine String-Länge Konvention verwenden, um die Einheit Eigentum Dekoration zu verwenden. Dieser Teil mag nicht schön, aber es macht den Job, und die gute Nachricht ist, dass Sie nicht noch einmal anschauen müssen!

StringColumnLengthConvention.cs:

using System.Reflection;
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.AcceptanceCriteria;
using FluentNHibernate.Conventions.Inspections;
using FluentNHibernate.Conventions.Instances;

namespace MyMappings
{
    public class StringColumnLengthConvention : IPropertyConvention, IPropertyConventionAcceptance
    {
        public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) { criteria.Expect(x => x.Type == typeof(string)).Expect(x => x.Length == 0); }
        public void Apply(IPropertyInstance instance)
        {
            int leng = 255;

            MemberInfo[] myMemberInfos = ((PropertyInstance)(instance)).EntityType.GetMember(instance.Name);
            if (myMemberInfos.Length > 0)
            {
                object[] myCustomAttrs = myMemberInfos[0].GetCustomAttributes(false);
                if (myCustomAttrs.Length > 0)
                {
                    if (myCustomAttrs[0] is MyDomain.DBDecorations.StringLength)
                    {
                        leng = ((MyDomain.DBDecorations.StringLength)(myCustomAttrs[0])).Length;
                    }
                }
            }
            instance.Length(leng);
        }
    }
}

Fügen Sie diese Konvention zu Ihrer Automapping-Konfiguration und dort haben Sie it-, wenn Sie eine bestimmte Länge wollen während ExportSchema führen, jetzt können Sie nur die String-Eigenschaft dekorieren -und nur das Eigentums- direkt in Ihrem Unternehmen!

Einer der konsequente Weg, dass ich gefunden ist:

Map(x => x.LongText, "LongText").CustomType<VarcharMax>().Nullable();

, in dem die VarcharMax und Klassen sind

public class VarcharMax : BaseImmutableUserType<String>
{
    public override object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return  (string)NHibernateUtil.String.NullSafeGet(rs, names[0]);
    }
    public override void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        //Change the size of the parameter
        ((IDbDataParameter)cmd.Parameters[index]).Size = int.MaxValue;
        NHibernateUtil.String.NullSafeSet(cmd, value, index);
    }
    public override SqlType[] SqlTypes
    {
        get { return new[] { new SqlType(DbType.String) }; }
    }
}

public abstract class BaseImmutableUserType<T> : NHibernate.UserTypes.IUserType
{
    public abstract object NullSafeGet(IDataReader rs, string[] names, object owner);
    public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
    public abstract SqlType[] SqlTypes { get; }

    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }

        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public Type ReturnedType
    {
        get { return typeof(T); }
    }

    public bool IsMutable
    {
        get { return false; }
    }
}

Hallo, ich kam in dieser Frage, mit dem gleichen Problem. Ich habe ein wenig sicherer Art und Weise, es zu tun, wie ich alle String-Felder standardmäßig nicht haben 10000 Zeichen will.

Als erstes registriere ich fließend nhibernate mit einigen Überschreibungen

...//snip
....Mappings(m => m.AutoMappings.Add(
                    AutoMap.AssemblyOf<Account>()
                     //Use my mapping overrides here 
                    .UseOverridesFromAssemblyOf<MyMappingOverride>()
                    .Conventions.Add(new MyConventions()).IgnoreBase<Entity>
                ))

Meine Mapping Überschreibung Klasse sieht wie folgt aus:

public class MyMappingOverride : IAutoMappingOverride<MyClass> {
       public void Override(AutoMapping<MyClass> mapping) {
           mapping.Map(x => x.LongName).Length(765);
       }
}

Dies ist nur für kleine Teilmenge von Entitäten mit langen Textwerten erforderlich. Vielleicht finden einige andere dies nützlich?

Wahrscheinlich Sie verwenden " NHibernate-Validator " als auch. Wenn ja, Fluent NHibernate werden alle der NHibernate-Validator zugehörigen Daten Anmerkungen automatisch, einschließlich der String-Länge, nicht null, etc.

betrachten
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top