Remplir un DataSet ou DataTable à partir d'un jeu de résultats de requête LINQ


137

Comment exposez-vous une requête LINQ en tant que service Web ASMX? Habituellement, à partir du niveau métier, je peux renvoyer un fichier tapé DataSetou DataTablequi peut être sérialisé pour le transport sur ASMX.

Comment puis-je faire de même pour une requête LINQ? Existe-t-il un moyen de remplir une requête tapée DataSetou DataTablevia une requête 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;
}

Comment puis-je obtenir le jeu de résultats d'une requête LINQ dans un DataSetou DataTable? Sinon, la requête LINQ est-elle sérialisable afin que je puisse l'exposer en tant que service Web ASMX?

Réponses:


87

Comme mentionné dans la question, IEnumerablea une CopyToDataTableméthode:

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

Pourquoi cela ne fonctionne-t-il pas pour vous?


29
À tous ceux qui se demandent pourquoi CopyToDataTable () ne fonctionne pas sur leur machine: Cette fonction ne fait pas partie de .NET 3.5 SP1 et ne sera pas non plus de .NET 4.0; il a été limité à IEnumerable <DataRows> et ne fonctionne pas pour IEnumerable <T> - bit.ly/dL0G5
devise

26

Pour effectuer cette requête sur une DataContextclasse, vous devez effectuer les opérations suivantes:

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

Sans le, as IEnumerable<DataRow>;vous verrez l'erreur de compilation suivante:

Impossible de convertir implicitement le type «System.Collections.Generic.IEnumerable» en «System.Collections.Generic.IEnumerable». Une conversion explicite existe (vous manquez un casting?)


22

Créez un ensemble d'objets de transfert de données, quelques mappeurs et renvoyez-le via le .asmx.
Vous ne devez jamais exposer directement les objets de la base de données, car une modification du schéma de procédure se propagera au consommateur de service Web sans que vous ne vous en rendiez compte.


15

Si vous utilisez un type de retour de IEnumerable, vous pouvez renvoyer directement votre variable de requête .



2

Si vous utilisez IEnumerablecomme type de retour, il renverra directement votre variable de requête.

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

Par souci d'exhaustivité, ces solutions ne fonctionnent pas pour EF Core (du moins pas pour EF Core 2.2). La diffusion vers IEnumerable<DataRow>, comme suggéré dans les autres réponses ici, échoue. L'implémentation de cette classe et de ces méthodes d'extension a fonctionné pour moi https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/implement-copytodatatable-where-type-not-a-datarow .

Pourquoi il n'est pas intégré à EF Core, je n'en ai aucune idée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.