4 Stimmen

Objekt aus Datenbankzeile erstellen

Nehmen wir an, ich baue eine Datenzugriffsschicht für eine Anwendung. Normalerweise habe ich eine Klassendefinition für jede Art von Objekt, das in der Datenbank gespeichert ist. Natürlich ruft der eigentliche Datenzugriff Daten in Form eines Datareaders, eines typisierten oder untypisierten Datensatzes oder Ähnlichem ab, normalerweise mit den Daten, die benötigt werden, um ein Objekt pro Zeile in den Ergebnissen zu erstellen.

Wie würden Sie vorgehen, um Ihre Objektinstanzen in der Datenschicht zu erstellen? Hätten Sie einen Konstruktor, der eine Datenreihe annimmt? Wenn ja, wie würden Sie das typsicher machen? Oder würden Sie Ihren Konstruktor für jedes Feld, das Sie instanziieren wollen, einen Parameter auflisten lassen, auch wenn es viele Felder geben könnte? Würden Sie diesen Konstruktor als "intern" kennzeichnen?

7voto

Eric Z Beard Punkte 36325

Wenn Sie mit DataRow oder SqlDataReader nicht zufrieden sind, sollten Sie sich ein ORM-System wie Linq to Sql oder nHibernate ansehen, anstatt das Rad selbst neu zu erfinden.

(Dies wird übrigens als "ActiveRecord"-Muster bezeichnet)

3voto

Anthony Mastrean Punkte 20992

Ich empfehle Ihnen dringend, ein ORM-Tool zu verwenden. Selbst einfache Projekte können ORM schnell und unauffällig nutzen... schauen Sie sich insbesondere an Schloss 's ActiveRecord Tool (das auf NHibernate aufgesetzt wird, um die Modelldeklaration zu vereinfachen).

2voto

David Basarab Punkte 69965

Ich habe dies mit Hilfe der Reflexion erreicht. Dabei benenne ich die Spalte aus der Select-Anweisung des Objekts.

Dies setzt voraus, dass Sie eine Hilfsklasse Templated haben. Wenn Sie sie selbst auf das Objekt anwenden wollen, können Sie einfach alle T durch das Objekt ersetzen.

Dies ist ein Beispiel:

private T ObjectFromRow(DataRow row)
{
    Type t = typeof(T);

    T newObj = (T)Activator.CreateInstance(t);

    System.Reflection.PropertyInfo[] properties = t.GetProperties();

    for (int i = 0; i < properties.Length; i++)
    {
        if (!properties[i].CanWrite)
        {
            continue;
        }

        if (!row.Table.Columns.Contains(properties[i].Name))
        {
            continue;
        }

        if (row[properties[i].Name] == DBNull.Value)
        {
            continue;
        }

        if (properties[i].PropertyType == typeof(string))
        {
            properties[i].SetValue(newObj, row[properties[i].Name], null);
        }
        else if (properties[i].PropertyType == typeof(double))
        {
            properties[i].SetValue(newObj, double.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(int))
        {
            properties[i].SetValue(newObj, int.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(DateTime))
        {
            properties[i].SetValue(newObj, DateTime.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(bool))
        {
            properties[i].SetValue(newObj, bool.Parse(row[properties[i].Name].ToString()), null);
        }
    }

    return newObj;
}

1voto

Anthony Mastrean Punkte 20992

@Joel (bezüglich komplexer Abfragen, Verknüpfungen usw.)

Das NHibernate- und Castle-ActiveRecord-Tool kann sehr komplexe Abfragen und Verknüpfungen über Klassenbeziehungen und eine gründliche 'Expression'-Klasse (die Sie zu den Abfragemethoden hinzufügen können) oder die Verwendung der 'Hibernate Query Language' (HQL) verarbeiten.

Sie können jede dieser Angaben googeln, die offizielle Dokumentation oder sehen Sie sich die großartige Sommer von NHibernate Screencasts.

1voto

David Robbins Punkte 10000

Als Alternative zu NHibernate & Castle können Sie einen Blick auf SubSonic . Dieses verwendet ebenfalls ActiveRecord, ist aber eher ein Schweizer Taschenmesser als NHibernate.

EDIT。

Hier ist ein Muster aus der SubSonic-Dokumentation:

Simple Select with string columns

            int records = new Select("productID").
                 From("Products").GetRecordCount();

            Assert.IsTrue(records == 77);

Simple Select with typed columns

            int records = new Select(Product.ProductIDColumn, Product.ProductNameColumn).
                From<Product>().GetRecordCount();
            Assert.IsTrue(records == 77);

Und einige weitere Beispiele :

Standard Deviation

    const double expected = 42.7698669325723;

    // overload #1
    double result = new
        Select(Aggregate.StandardDeviation("UnitPrice"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #2
    result = new
        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #3
    result = new
        Select(Aggregate.StandardDeviation("UnitPrice", "CheapestProduct"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #4
    result = new
        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn, "CheapestProduct"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

Und einige Wildcard-Methoden :

 [Test]
        public void Select_Using_StartsWith_C_ShouldReturn_9_Records() {

            int records = new Select().From<Product>()
                .Where(Northwind.Product.ProductNameColumn).StartsWith("c")
                .GetRecordCount();
            Assert.AreEqual(9, records);
        }

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