Reputation: 6176
How do you expose a LINQ query as an ASMX web service?
Usually, from the business tier, I can return a typed DataSet
or a DataTable
which can be serialized for transport over ASMX.
How can I do the same for a LINQ query?
Is there a way to populate a typed DataSet
or a DataTable
via a LINQ query?
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;
}
How could I put the result set of a LINQ query into a DataSet
or a DataTable
?
Alternatively, can the LINQ query be serializable so that I can expose it as an ASMX web service?
Upvotes: 159
Views: 88842
Reputation: 292
If you use IEnumerable
as the return type, it will return your query variable directly.
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>();
Upvotes: 6
Reputation: 4536
For the sake of completeness, these solutions do not work for EF Core (at least not for EF Core 2.2). Casting to IEnumerable<DataRow>
, as suggested in the other answers here, fails. Implementing this class and extension methods worked for me https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/implement-copytodatatable-where-type-not-a-datarow.
Why it's not built into EF Core, I have not idea.
Upvotes: 3
Reputation:
To perform this query against a DataContext
class, you'll need to do the following:
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>();
Without the as IEnumerable<DataRow>;
you will see the following compilation error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)
Upvotes: 32
Reputation: 53125
As mentioned in the question, IEnumerable
has a CopyToDataTable
method:
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>();
Why won't that work for you?
Upvotes: 99
Reputation: 60580
If you use a return type of IEnumerable
, you can return your query variable directly.
Upvotes: 19
Reputation: 6102
Make a set of Data Transfer Objects, a couple of mappers, and return that via the .asmx.
You should never expose the database objects directly, as a change in the procedure schema will propagate to the web service consumer without you noticing it.
Upvotes: 25