2 Stimmen

Wie kann NHibernate einen String.Empty-Eigenschaftswert als NULL persistieren lassen

Ich habe eine ziemlich einfache Klasse, die ich in SQL Server über NHibernate (w/ Fluent Mappings) speichern möchte. Die Klasse besteht hauptsächlich aus optionalen Stringfeldern.

Mein Problem ist, dass ich die Klassenfelder standardmäßig auf string.empty setze, um NullRefExceptions zu vermeiden, und wenn NHibernate die Zeile in der Datenbank speichert, enthält jede Spalte eine leere Zeichenfolge anstelle von null.

Frage: Gibt es eine Möglichkeit, NHibernate dazu zu bringen, automatisch null zu speichern, wenn die String-Eigenschaft ein leerer String ist? Oder muss ich meinen Code mit if (string.empty)-Prüfungen überfrachten?

7voto

Jamie Ide Punkte 46985

Sie können dies mit einem UserType tun. Ich bin zu dem Schluss gekommen, dass Null-Strings in meinen Business-Klassen nutzlos (und lästig) sind, also konvertiere ich alle nullbaren String-Datenbankspalten in leere Strings und umgekehrt.

Fließender Gebrauch ist:

Map(x => x.MiddleName).CustomType(typeof(NullableString));

/// <summary>
/// UserType for string properties that are database nullable. Using this type
/// will substitue empty string for null when populating object properties
/// and null for empty string in database operations.
/// </summary>
/// <example>
/// Map(x => x.MiddleName).Length(30).Nullable().CustomType(typeof(NullableString));
/// </example>
public class NullableString : IUserType
{
    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 NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var valueToGet = NHibernateUtil.String.NullSafeGet(rs, names[0]);
        return valueToGet ?? string.Empty;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var stringObject = value as string;
        object valueToSet = string.IsNullOrEmpty(stringObject) ? null : stringObject;
        NHibernateUtil.String.NullSafeSet(cmd, valueToSet, index);
    }

    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 SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(DbType.String)};
        }
    }

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

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

5voto

Abel Punkte 53946

NHibernate tut, was Sie von ihm verlangen. Auf der einen Seite sagen Sie, dass Sie versuchen, Folgendes zu vermeiden NullReferenceException , auf der anderen Seite versuchen Sie zu sparen NULL in der Datenbank, wenn ein Wert nicht null ist. Das klingt für mich nach einem Widerspruch. Anstatt zu versuchen, diesen Funktionsfehler zu umgehen, sollten Sie entweder Nullen zulassen (und die Daten überprüfen, um NREs zu verhindern) oder Nullen nicht zulassen.

Wenn es einen speziellen Fall gibt, den Sie mit NULL-Feldern vs. leeren Feldern abdecken wollen, sollten Sie das Lesen der korrekten Daten in Betracht ziehen (und nicht initiieren, um String.Empty ). Wenn Sie eine leere Zeichenkette mit einem Nullwert in dieser Datenbank gleichsetzen, initialisieren Sie einfach alle Felder mit der leeren Zeichenkette, um es einfach und konsistent zu halten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X