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?

Geoff Dalgas
la source

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?

Jon Galloway
la source
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?)

C1pher
la source
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.

Lars Mæhlum
la source
15

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

Dave Ward
la source
11

Créez un objet de classe et renvoyez un list(T)de la requête.

Brian Childress
la source
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>();
Vijay S
la source
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.

Gabriel Magana
la source