wake-up-neo.com

Konvertieren Sie DataTable in IEnumerable <T> in ASP.NET Core 2.0

Ich muss eine IEnumerable aus einer DataTable generieren, die ich als Eingabe von einem anderen System erhalte. Der folgende Code hat in ASP.NET 4.6.1 funktioniert. 

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
    {
        var data = dataTable.AsEnumerable().Select(row =>
            new UserAssignmentDto
            {
                Id = ((string)row["AssignmentNumber"]),
                Position = (string) row["EsrPositionTitle"],

            });

        return data;
    }

'DataTable' enthält jedoch keine Definition mehr für 'AsEnumerable' in ASP.NET Core 2.0. 

Was wäre der effizienteste Weg, um das IEnumerable zu erzeugen, das ich brauche?

6
Roddy Balkan

Eine der effizientesten Maßnahmen, die Sie tun können, ist, den Code für die Iteration selbst zu schreiben, indem Sie anstelle von LINQ eine for-Schleife verwenden, einfach durch die DataTable-Zeilen iterieren und den Rückgabewert der IEnumerable<UserAssignmentDto>-Methode "von Hand" erstellen.

Da DataTable keinen Enumerator in .NET Core 2.0 implementiert, müssen Sie eine "reguläre" for-Schleife verwenden, um die Zeilen zu durchlaufen. Sie können foreach nicht verwenden, da DataTable IEnumerable nicht in .NET Core 2.0 implementiert hat.

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
    var retList = new List<UserAssignmentDto>();

    for(int i = 0; i < dataTable.Rows.Count; i++)
    {
          var row = dataTable.Rows[i];

          var temp = new UserAssignmentDto(){
              Id = row["AssignmentNumber"],
              Position = row["EsrPositionTitle"]
          };

          retList.Add(temp);     
    }

    return retList;
}
2
Brian Ogden

Das richtige Nuget-Paket für .net Core 2 ist System.Data.DataSetExtensions

4

Hier ist eine generische AsEnumerable-Erweiterungsfunktion, um die klassische AsEnumerable () - Funktion nachzuahmen und eine Enumerable-Sammlung von DataRows aus einer DataTable zurückzugeben. Kann für jemanden nützlich sein, der die Menge an Refactoring nachahmen möchte, die für die Portierung des Codes in den .net Core erforderlich ist.

    public static IEnumerable<DataRow> AsEnumerable(this DataTable table)
    {
        for (int i = 0; i < table.Rows.Count; i++)
        {
            yield return table.Rows[i];
        }
    }
4
SteveD

Da Enumerable () in .NET Core 2.0 vorhanden ist, müssen Sie lediglich einen Verweis auf System.Data.DataExtensions hinzufügen, wie in der Antwort auf eine ähnliche Frage erwähnt. LINQ to DataSet, DataTable.AsEnumerable () nicht erkannt

3
r2k83

Nicht sehr effizient, aber als Alternative können Sie die Select-Methode verwenden:

DataRow[] rows= dataTable.Select();

Und jetzt haben Sie eine IEnumerable von Zeilen. Diese Methode kann jemandem helfen:

public static List<T> ConvertDataTableToGenericList<T>(DataTable dt)
{
     var columnNames = dt.Columns.Cast<DataColumn>()
            .Select(c => c.ColumnName)
            .ToList();

     var properties = typeof(T).GetProperties();
     DataRow[] rows= dataTable.Select();
     return rows.Select(row =>
     {
          var objT = Activator.CreateInstance<T>();
          foreach (var pro in properties)
          {
              if (columnNames.Contains(pro.Name))
                   pro.SetValue(objT, row[pro.Name]);
          }

          return objT;
     }).ToList();
}
2
Naser Yousefi

Die Effizienz hängt vom Anwendungsfall ab. Die Brians-Antwort ist gut, wenn Sie das gesamte Ergebnis benötigen. Es kann durch Vorbelegung der Kapazität für List verbessert werden, um eine Größenänderung oder Änderung des Arrays zu vermeiden, aber im Allgemeinen ist es gut. Ich würde lieber List oder Array zurückgeben, um genauer zu zeigen, was es tut, aber das ist meine persönliche Entscheidung. Es speichert den Status von DataTable zum Zeitpunkt des Aufrufs, der je nach Bedarf gut oder schlecht sein kann.

Wenn die Möglichkeit besteht, dass Sie nicht alle Elemente benötigen oder das IEnumerable-Element überhaupt nicht aufgelistet werden, ist es möglicherweise effizienter, einen echten Enumerator zu erstellen:

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
        {
            foreach (DataRow row in dataTable)
            {
               yield return new UserAssignmentDto()
                {
                    Id = row["AssignmentNumber"],
                    Position = row["EsrPositionTitle"]
                };               
            }
        }

Es ist aber immer noch nicht die schnellste Option. Sie können es vermeiden, jedes Mal ein neues Objekt zuzuweisen, wenn Sie nachgeben. Sie können jedes Mal dasselbe Objekt zurückgeben, indem Sie die Eigenschaften entsprechend festlegen. Es hat den offensichtlichen Nachteil, dass Sie keine Objekte aus solchen IEnumerable-Dateien für die spätere Verwendung speichern können, aber manchmal brauchen Sie das nicht.

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
        {
            UserAssignmentDto ret = new UserAssignmentDto();
            foreach (DataRow row in dataTable)
            {
                ret.Id = row["AssignmentNumber"];
                ret.Position = row["EsrPositionTitle"];
                yield return ret;
            }
        }
1
Antonín Lejsek

Sie können myDataTable.Select(); verwenden, es gibt ein Array aller DataRow zurück

0
Nitika Chopra