Wypełnianie DataSet lub DataTable z zestawu wyników zapytania LINQ


137

Jak udostępnić zapytanie LINQ jako usługę sieciową ASMX? Zwykle z poziomu biznesowego mogę zwrócić wpisany DataSetlub DataTableserializowany do transportu przez ASMX.

Jak mogę zrobić to samo dla zapytania LINQ? Czy istnieje sposób na wypełnienie wpisanego DataSetlub DataTableza pośrednictwem zapytania LINQ?

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;
}

Jak mogę uzyskać zestaw wyników zapytania LINQ do DataSetlub DataTable? Alternatywnie, czy zapytanie LINQ można serializować, aby można było je ujawnić jako usługę sieci Web ASMX?

Odpowiedzi:


87

Jak wspomniano w pytaniu, IEnumerablema CopyToDataTablemetodę:

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>();

Dlaczego to nie zadziała?


29
Do wszystkich, którzy zastanawiają się, dlaczego CopyToDataTable () nie działa na ich komputerze: Ta funkcja nie jest częścią .NET 3.5 SP1 ani nie będzie w .NET 4.0; został ograniczony do IEnumerable <DataRows> i nie działa dla IEnumerable <T> - bit.ly/dL0G5
motto

26

Aby wykonać to zapytanie w stosunku do DataContextklasy, musisz wykonać następujące czynności:

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>();

Bez tego as IEnumerable<DataRow>;zobaczysz następujący błąd kompilacji:

Nie można niejawnie przekonwertować typu „System.Collections.Generic.IEnumerable” na „System.Collections.Generic.IEnumerable”. Istnieje jawna konwersja (brakuje Ci obsady?)


22

Stwórz zestaw obiektów transferu danych, kilka mapperów i zwróć go za pośrednictwem pliku .asmx.
Nigdy nie należy bezpośrednio ujawniać obiektów bazy danych, ponieważ zmiana w schemacie procedury będzie propagowana do konsumenta usługi WWW bez zauważenia tego.


15

Jeśli używasz zwracanego typu IEnumerable, możesz bezpośrednio zwrócić zmienną zapytania .



2

Jeśli użyjesz IEnumerablejako typu zwracanego, zwróci on bezpośrednio zmienną zapytania.

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>();

0

Ze względu na kompletność te rozwiązania nie działają w przypadku EF Core (przynajmniej nie w przypadku EF Core 2,2). Przesyłanie do IEnumerable<DataRow>, jak sugerowano w innych odpowiedziach, kończy się niepowodzeniem. Wdrożenie tej klasy i metod rozszerzających zadziałało dla mnie https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/implement-copytodatatable-where-type-not-a-datarow .

Dlaczego nie jest wbudowany w EF Core, nie mam pojęcia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.