Füllen eines DataSet oder einer DataTable aus einer LINQ-Abfrage-Ergebnismenge

137

Wie macht man eine LINQ-Abfrage als ASMX-Webdienst verfügbar? Normalerweise kann ich auf der Business-Ebene eine Eingabe zurückgeben DataSetoder DataTablediese für den Transport über ASMX serialisieren.

Wie kann ich dasselbe für eine LINQ-Abfrage tun? Gibt es eine Möglichkeit, eine Eingabe zu füllenDataSet oder DataTableeine LINQ-Abfrage zu füllen?

public static MyDataTable CallMySproc()
{
    string conn = "...";

    MyDatabaseDataContext db = new MyDatabaseDataContext(conn);
    MyDataTable dt = new MyDataTable();

    // execute a sproc via LINQ
    var query = from dr
                in db.MySproc().AsEnumerable
                select dr;

    // copy LINQ query resultset into a DataTable -this does not work !    
    dt = query.CopyToDataTable();

    return dt;
}

Wie kann ich die Ergebnismenge einer LINQ-Abfrage in ein DataSetoder bekommen?DataTable ? Ist die LINQ-Abfrage alternativ serialisierbar, damit ich sie als ASMX-Webdienst verfügbar machen kann?

Geoff Dalgas
quelle

Antworten:

87

Wie in der Frage erwähnt, IEnumerablehat eine CopyToDataTableMethode:

IEnumerable<DataRow> query =
    from order in orders.AsEnumerable()
    where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
    select order;

// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();

Warum funktioniert das bei Ihnen nicht?

Jon Galloway
quelle
29
An alle, die sich fragen, warum CopyToDataTable () auf ihrem Computer nicht funktioniert: Diese Funktion ist weder Teil von .NET 3.5 SP1 noch von .NET 4.0. Es wurde auf IEnumerable <DataRows> beschränkt und funktioniert nicht für IEnumerable <T> - bit.ly/dL0G5
Motto
26

Um diese Abfrage für eine DataContextKlasse durchzuführen , müssen Sie Folgendes tun:

MyDataContext db = new MyDataContext();
IEnumerable<DataRow> query = 
    (from order in db.Orders.AsEnumerable()
        select new
        {
            order.Property,
            order.Property2
        })
    as IEnumerable<DataRow>;
return query.CopyToDataTable<DataRow>();

Ohne das as IEnumerable<DataRow>;wird der folgende Kompilierungsfehler angezeigt:

Der Typ 'System.Collections.Generic.IEnumerable' kann nicht implizit in 'System.Collections.Generic.IEnumerable' konvertiert werden. Es gibt eine explizite Konvertierung (fehlt Ihnen eine Besetzung?)

C1pher
quelle
22

Erstellen Sie eine Reihe von Datenübertragungsobjekten, einige Mapper, und geben Sie diese über die .asmx-Datei zurück.
Sie sollten die Datenbankobjekte niemals direkt verfügbar machen, da eine Änderung des Prozedurschemas an den Webdienstkonsumenten weitergegeben wird, ohne dass Sie dies bemerken.

Lars Mæhlum
quelle
15

Wenn Sie einen Rückgabetyp von verwenden IEnumerable, können Sie Ihre Abfragevariable direkt zurückgeben.

Dave Ward
quelle
11

Erstellen Sie ein Klassenobjekt und geben Sie eine list(T)der Abfragen zurück.

Brian Childress
quelle
2

Wenn Sie IEnumerableals Rückgabetyp verwenden, wird Ihre Abfragevariable direkt zurückgegeben.

MyDataContext db = new MyDataContext();
IEnumerable<DataRow> query = 
    (from order in db.Orders.AsEnumerable()
        select new
        {
            order.Property,
            order.Property2
        })
    as IEnumerable<DataRow>;
return query.CopyToDataTable<DataRow>();
Vijay S.
quelle
0

Der Vollständigkeit halber funktionieren diese Lösungen nicht für EF Core (zumindest nicht für EF Core 2.2). Das Casting auf IEnumerable<DataRow>schlägt fehl, wie in den anderen Antworten hier vorgeschlagen. Die Implementierung dieser Klassen- und Erweiterungsmethoden funktionierte für mich unter https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/implement-copytodatatable-where-type-not-a-datarow .

Warum es nicht in EF Core eingebaut ist, weiß ich nicht.

Gabriel Magana
quelle