Frage

Ich habe eine Datenebene Auswahlmethode, die eine Datentabelle zurückgibt. Es ist von einer Business-Tier-Methode aufgerufen, die eine stark typisierte generische Liste dann zurückgeben sollte.

Was ich tun möchte, ist sehr ähnlich (aber nicht das gleiche wie) diese Frage:
Wie Sie eine Datatable in eine generische Liste konvertieren?

Was anders ist, ist, dass ich die Liste will stark typisierte Objekte enthalten, anstatt datarows (auch, ich habe nicht Linq verfügbar hier noch) nicht.

Ich bin besorgt über die Leistung. Die Business-Tier-Methode wird wiederum von der Präsentationsebene aufgerufen werden, und die Ergebnisse werden zur Anzeige für den Benutzer wiederholt werden. Es scheint sehr verschwenderisch eine zusätzliche Iteration an dem Business-Tiere hinzufügen, es nur tun, sofort wieder für die Präsentation, so möchte ich so schnell wie möglich sein.

Dies ist eine gemeinsame Aufgabe, also bin ich wirklich für ein gutes Muster suchen, der wiederholt über werden kann und immer wieder.

War es hilfreich?

Lösung

Sie wissen, die Struktur des DataTable und das typisierte Objekts vor der Zeit? Sie könnten einen Delegaten verwenden, um die Zuordnung zu tun. Wenn Sie dies nicht tun (das heißt alles, was Sie wissen, ist ein Type und Eigenschaften) gibt es Möglichkeiten zur Beschleunigung dynamischer Mitglied Zugang (wie HyperDescriptor).

So oder so, sollten Sie eine Iteratorblock; auf diese Weise, Sie müssen die Objekte nicht um einen vollständigen zweiten Zeitpuffer; natürlich, wenn Sie nur den Umgang mit kleineren rowcounts ist dies kein Problem.

Können Sie eine dieser Punkte klären? Ich kann viel mehr Detail hinzufügen ...

Am einfachsten, was falsch ist mit:

DataTable table = new DataTable {
    Columns = {
        {"Foo", typeof(int)},
        {"Bar", typeof(string)}
     }
};
for (int i = 0; i < 5000; i++) {
    table.Rows.Add(i, "Row " + i);
}

List<MyType> data = new List<MyType>(table.Rows.Count);
foreach (DataRow row in table.Rows) {
    data.Add(new MyType((int)row[0], (string)row[1]));
}

(die Probleme in der oben könnten den richtigen Ansatz lenken ...)

Andere Tipps

Das Problem bei der Probe oben ist, dass es schrecklich langsam ist. Ich habe eine Datentabelle mit etwa 400 Zeilen und diese Umwandlung dauert gut 5 oder 6 Sekunden!

Es scheint wie eine ziemlich gemeinsame Aufgabe, so dass ich bin überrascht, jemand hier mit einer leistungsfähigere Lösung nicht zu sehen.

* Update !! * Just for Kicks, dachte ich, ich würde versuchen, LINQ Umwandlung anstelle durch die Datentabelle von Iterieren und dem Hinzufügen von meiner Liste. Im Folgenden ist das, was ich getan habe:

   List<MyObject> returnList = new List<MyObject>();

   MyDataTable dtMyData = new MyTableAdapter().GetMyData();

   returnLists = (from l in dtMyData
                 select new MyObject
                 {
                    Active = l.IsActive,
                    Email = l.Email,
                    //...
                    //About 40 more properties
                    //...
                    ZipCode = l.Zipcode
                  }).ToList();

Die erste Methode (durch jede Zeile Iterieren) nahm 5,3 Sekunden und die Methode mithilfe von LINQ dauerte 1,8 Sekunden!

Sie müssen durch die datarows iterieren und sie in Ihre Objekte irgendwann sowieso konvertieren, aber man konnte eine eigene Sammlung mit einem Konstruktor schreiben, die eine Sammlung von datarows nimmt und dass wandelt jedes Element in Ihren Objekttyp, wenn stattdessen die angeforderte alle auf einmal.

Sagen Sie Ihre benutzerdefinierte Sammlung definieren, die IList<T> implementiert. Es könnte dann zwei interne Felder hat - einen Verweis auf die Sammlung von datarows und einer List<T>. Die List<T> würde auf die Länge der Sammlung von datarows initialisiert werden, aber mit Null-Werten.

Jetzt im Indexer können Sie überprüfen, ob der List<T> Wert an diesem Index enthält und wenn nicht können Sie das Objekt erstellen Mitteln unabhängig von Nutzen wäre und dort zu speichern, bevor es zurückkehrt.

Dies würde die Schaffung Ihrer Objekte verschieben, bis sie angefordert wurden, und Sie würden nur die Objekte erstellen, die angefordert wurden.

Ihre Objekte müssen wahrscheinlich einen Konstruktor eine DataRow nehmen oder würden Sie eine Art Fabrik benötigen, sie zu schaffen, aber das ist ein anderes Thema.

Sie einfach ein wenig mehr Benutzer zur Verfügung zu stellen - Freundlichkeit Mark Antwort auf eine einfache Konsolenanwendung:

class Program
{
    static void Main(string[] args)
    {
        //define a DataTable obj
        DataTable table = new DataTable
        {
            Columns = {
            {"Foo", typeof(int)},
            {"Bar", typeof(string)}
         }
        };
        //populate it the DataTable 
        for (int i = 0; i < 3; i++)
        {
            table.Rows.Add(i, "Row " + i);
        }

        List<MyType> listWithTypedObjects= new List<MyType>(table.Rows.Count);
        foreach (DataRow row in table.Rows)
        {
            listWithTypedObjects.Add(new MyType((int)row[0], (string)row[1]));
        }

        Console.WriteLine(" PRINTING THE POPULATED LIST ");
        foreach (MyType objMyType in listWithTypedObjects)
        {
            Console.Write(" I have object of the type " + objMyType.ToString() + " => " );
            Console.Write(" with Prop1OfTypeInt " + objMyType.Prop1OfTypeInt.ToString() + " , ");
            Console.WriteLine(" with Prop1OfTypeInt " + objMyType.Prop2OfTypeString.ToString() + "  "); 
        }

        Console.WriteLine(" \n \n \n HIT A KEY TO EXIT THE PROGRAM ");
        Console.ReadKey();
    }
}

class MyType {

    public int Prop1OfTypeInt { get; set; }
    public string Prop2OfTypeString { get; set; } 

    /// <summary>
    /// Note the order of the passed parameters is important !!!
    /// </summary>
    public MyType( int prop1OfTypeInt , string prop2OfTypeString)
    {
        this.Prop1OfTypeInt = prop1OfTypeInt;
        this.Prop2OfTypeString = prop2OfTypeString; 

    }
}
public partial class issuereceive_manageroffice_bal
{
    public int issue_id{get;set;}
    public string process{get;set;}
    public DateTime issue_date{get;set;}
    public TimeSpan issue_time{get;set;}
    public string eg_no{get;set;}
    public string lotno{get;set;}
    public string clarity{get;set;}
    public string sieves{get;set;}
    public string shape{get;set;}
    public double issue_carat{get;set;}
    public int issue_pieces{get;set;}
    public int receive_pieces{get;set;}
    public double receive_carat{get;set;}
    public int kp_pieces{get;set;}
    public decimal kp_carat{get;set;}
    public double loss{get;set;}
    public string issue_manager{get;set;}
    public string issue_by{get;set;}
    public string receive_by{get;set;}
    public int status{get;set;}
    public DateTime receive_date{get;set;}
    public string receive_time{get;set;}
    public int factory_id{get;set;}

}


List<issuereceive_manageroffice_bal> issue_receive_list = new List<issuereceive_manageroffice_bal>();
issue_receive_list =
      (from DataRow dr in DataTable.Rows
      select new issuereceive_manageroffice_bal()
           {
               issue_id = 0,
               issue_time = TimeSpan.Parse("0"),
               receive_time = null,
               shape = null,
               process = dr["process"].ToString(),
               issue_date = Convert.ToDateTime(dr["issue_date"]),
               eg_no = dr["eg_no"].ToString(),
               lotno = dr["lotno"].ToString(),
               clarity = dr["clarity"].ToString(),
               sieves = dr["sieves"].ToString(),
               issue_carat = dr["issue_carat"].ToString() != "" ? double.Parse(dr["issue_carat"].ToString()) : 0,
               issue_pieces = dr["issue_pieces"].ToString() != "" ? int.Parse(dr["issue_pieces"].ToString()) : 0,
               receive_carat = dr["receive_carat"].ToString() != "" ? double.Parse(dr["receive_carat"].ToString()) : 0,
               kp_pieces = dr["kp_pieces"].ToString() != "" ? int.Parse(dr["kp_pieces"].ToString()) : 0,
               kp_carat = dr["kp_carat"].ToString() != "" ? decimal.Parse(dr["kp_carat"].ToString()) : 0,
               loss = dr["loss"].ToString() != "" ? double.Parse(dr["loss"].ToString()) : 0,
               issue_manager = dr["lotno"].ToString(),
               issue_by = dr["issue_by"].ToString(),
               receive_by = dr["receive_by"].ToString(),
               status = dr["status"].ToString() != "" ? int.Parse(dr["status"].ToString()) : 0,
               receive_date = Convert.ToDateTime(dr["receive_date"]),
               factory_id = dr["factory_id"].ToString() != "" ? int.Parse(dr["factory_id"].ToString()) : 0,

           }).ToList();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top