How to merge collection in EF query - entity-framework

An order have many order-detail
I want to query all order-detail of some order and combine them into only one IEnumerable
How can I do that? The code below return IEnumerable<IEnumerable<OrderDetail>>
db.Order.Where(o=>o.OrderDate > date1).select(o=>o.OrderDetail)

Use SelectMany()
Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.
db.Order.Where(o => o.OrderDate > date1).SelectMany(o => o.OrderDetail);

Related

linq minus of to sum values

I want below SQL Query to be written in entity framework or LINQ.Can any one please help me on this
SQL Query:
select sum(CreditAmount)-sum(DebitAmount)
from [dbo].[JournalEntries]
where FKSubscriberID =3 and FKAccountID =1
In general, assuming C#, convert SQL to LINQ by converting phrases in LINQ comprehension syntax order, and if SQL has table aliases, use them in LINQ as range variables. Functions such as DISTINCT or TOP are called as functions over the whole query at the end. Doing multiple SUM in one query without the optimization #JonSkeet suggests requires an empty group...by to create an aggregate and then First() to reduce to a value:
(from je in dbo.JournalEntries
where je.FKSubscriberID == 3 && je.FKAccountID == 3
group je by 1 into jeg
select jeg.Sum(je => je.CreditAmount) - jeg.Sum(je => je.DebitAmount)).First()
Without the single group, you can aggregate the difference with
(from je in dbo.JournalEntries
where je.FKSubscriberID == 3 && je.FKAccountID == 3
select je.CreditAmount-je.DebitAmount).Sum()

EntityFramework counting of query results vs counting list

Should efQuery.ToList().Count and efQuery.Count() produce the same value?
How is it possible that efQuery.ToList().Count and efQuery.Count() don't produce the same value?
//GetQuery() returns a default IDbSet which is used in EntityFramework
using (var ds = _provider.DataSource())
{
//return GetQuery(ds, filters).Count(); //returns 0???
return GetQuery(ds, filters).ToList().Count; //returns 605 which is correct based on filters
}
Just ran into this myself. In my case the issue is that the query has a .Select() clause that causes further relationships to be established which end up filtering the query further as the relationship inner join's constrain the result.
It appears that .Count() doesn't process the .Select() part of the query.
So I have:
// projection created
var ordersData = orders.Select( ord => new OrderData() {
OrderId = ord.OrderId,
... more simple 1 - 1 order maps
// Related values that cause relations in SQL
TotalItemsCost = ord.OrderLines.Sum(lin => lin.Qty*lin.Price),
CustomerName = ord.Customer.Name,
};
var count = ordersData.Count(); // 207
var count = ordersData.ToList().Count // 192
When I compare the SQL statements I find that Count() does a very simple SUM on the Orders table which returns all orders, while the second query is a monster of 100+ lines of SQL that has 10 inner joins that are triggered by the .Select() clause (there are a few more related values/aggregations retrieved than shown here).
Basically this seems to indicate that .Count() doesn't take the .Select() clause into account when it does its count, so those same relationships that cause further constraining of the result set are not fired for .Count().
I've been able to make this work by explicitly adding expressions to the .Count() method that pull in some of those aggregated result values which effectively force them into the .Count() query as well:
var count = ordersData.Count( o=> o.TotalItemsCost != -999 &&
o.Customer.Name != "!##"); // 207
The key is to make sure that any of the fields that are calculated or pull in related data and cause a relationship to fire, are included in the expression which forces Count() to include the required relationships in its query.
I realize this is a total hack and I'm hoping there's a better way, but for the moment this has allowed us at least to get the right value without pulling massive data down with .ToList() first.
Assuming here that efQuery is IQueryable:
ToList() actually executes a query. If changes to data in the datastore, between calls to ToList() and .Count(), result in a different resultset, calling ToList() will repopulate the list. ToList().Count and .Count() should then match until the data in the store changes the resultset again.

Sub Query in select clause with Squeryl

I'm trying to replicate the following query usine Squeryl.
SELECT c.order_number,p.customer,p.base,(
SELECT sum(quantity) FROM "Stock" s where s.base = p.base
) as stock
FROM "Card" c, "Part" p WHERE c."partId" = p."idField";
I have the following code for selecting the Cards and Parts but I cannot see a way to add a sumation into the select clause.
from(cards, parts)((c,p) =>
where(c.partId === p.id)
select(c,p)
Any help is much appreciated!
In Squeryl, you can use any Queryable object in the from clause of your query. So, to create a subquery, something like the following should work for you:
def subQuery = from(stock)(s => groupBy(s.base) compute(sum(s.quantity)))
from(cards, parts, subquery)((c, p, sq) =>
where(c.partId === p.idField and sq.key === p.base)
select(c.orderNumber, p.customer, sq.measures))
Of course the field names may vary slightly, just guessing at the class definitions. If you want the whole object for cards and parts instead of the single fields from the original query - just change the select clause to: select(c, p, sq.measures)

How to write query in Entity Framework

I'm new to Entity Framework. I have a database query which I need to convert to Entity Framework. how to write the query in LinQ to Enity
Can someone help me on that?
SELECT
FLD1,
FLD2,
SUM(FLD3),
(TO_CHAR(FLD4,'MM/DD/YYYY'))
FROM
TABLE1
WHERE
(FLD2=XXX ) AND
(FLD3 BETWEEN TO_DATE(VARDATE,'MMDDYYYY') AND TO_DATE(VARDATE1,'MMDDYYYY'))
GROUP BY
FLD1,
FLD2,
FLD4
Well...info is sparse and you filled it with a lot of different cases something like this would do.
_context.SomeObject
.Where(x=>x.SomeField == "SomeValue" && x.SomeField > 5 && x.SomeField < 10)
.Select(x=>new { x.SomeField1, x.SomeField2, x.SomeField2, SomeField4 = x.SomeChildCollection.Sum(y=>y.SomeChildvalue)
.GroupBy(x=>new {x.SomeField1, x.SomeField2, x.SomeField3})
.ToList()
This would result in a group where the key was an object with the values SomeField1, SomeField2, SomeField3, and the object would be the an anonymous projection with the 4 properties in the Select.
In some kinds of comparisions regarding dates you might need to use EntityFunctions.

Linq-to-Entities match ID in list of integers in a compiled query

I'm trying to find a way to implement a Linq-to-Entities compiled query of the form:
Func<MyEntities, List<int>, IQueryable<MyClass>> query = System.Data.Objects.CompiledQuery.Compile(
(MyEntities entities, List<int> IDs) => (
(from au in entities.Mine where IDs.Any(x => x == au.ID) select au)
));
Because only scalar parameters can be passed to CompiledQuery.Compile the above fails. I'm trying to find some clever way to pass a comma delimited list of integers as a string and use that in the L2E query along the lines of:
Func<MyEntities, string, IQueryable<MyClass>> query = System.Data.Objects.CompiledQuery.Compile(
(MyEntities entities, string IDs) => (
(from au in entities.Mine where IDs.Split(',').Any(x => Convert.ToInt32(x) == au.ID) select au)
));
But that doesn't work due to the unsupported Split function.
Any clever ideas about how this could be implemented?
I'm not sure if this could possibly work, but maybe try to use join of List<int> IDs and MyEntities entities?
I ended up finding a way to do it but it's way too slow at around 3s.
string ids = "|" + String.Join("|", new List<int> { 4, 5, 6, 7, 8, 9, 10, 20, 23, 34 }) + "|";
Func<MyEntities, string, IQueryable<MyClass>> query = System.Data.Objects.CompiledQuery.Compile(
(MyEntities entities, string IDs) => (
(from au in entities.Mine where IDs.Contains("|" + SqlFunctions.StringConvert((decimal)au.ID).Trim() + "|")select au)
));
Back to the drawing board.
You can't.
What does CompiledQuery do? It pre-converts the query to a canonical command tree -- an intermediate representation used to generate SQL by the provider.
The SQL for a command with a scalar param is the same structure regardless of the param value. But the SQL generated for, say, a list of 2 items will be structurally different from the SQL afor a list of 3 items, because it takes one fewer OR predicate in its WHERE clause. Most DB servers won't take lists as a param value, after all.
Your string/| kludge works because you're now passing only one param, not a list, to the DB server. But as you've seen, the server can't index such a query, so it will be slow.