Group By and Count query fails to translate from Linq to SQL - tsql

I have created the linq query shown below, in LINQPad. This fails when using EF Core 3.0. I know the issues around Group By and the reason EF Core fails when the translation cannot be made rather than pulling back all the data and doing it client side. My problem is that I have so far not worked out if it is possible to do what I want to do to get my query to run.
My table has a CorrelationId which is the same value only for related records. I need to create a query which just returns the records where the CorrelationId only exists once. If the CorrelationId appears more than once then that indicates there are related records and none of these should be returned. The query must run on the server so pulling back all the data is not an option.
Here is my Linq query that fails with the "...could not be translated. Either rewrite the query in a form that can be translated..." error.
from x in History
where
(
from d in History
group d by new {d.CorrelationId} into g
where g.Count() == 1
select new {Id = g.Key.CorrelationId}
).Contains(new { Id = x.CorrelationId })
select new {Id = x.Id, FileName = x.FileName}

Try using Any instead of Contains
.Any(y => y.Id == x.CorrelationId)

Related

How to increment a value using one command using entity framework

How can i transform this sql query to an EF linq command
"update dbo.table set col1= col1 + 1 where Id = 27"
i want to execute this query using one command to avoid concurrency problems
in case of another client modify the record in the same time
i'm looking for doing that using EF but in one command
i tried this but i'm looking for a better solution :
context.table1.FromSqlInterpolated($"update dbo.table set col1= col1+ 1 where Id=27").FirstOrDefaultAsync();
I would propose to use linq2db.EntityFrameworkCore (note that I'm one of the creators)
Then you can do that with ease:
await context.table1.Where(x => x.Id == 27)
.Set(x => x.Col1, prev => prev.Col1 + 1)
.UpdateAsync();
There are ways to update a column without first querying, but the problem you have is that the update is based on the existing value.
Entity Framework can't help you there. You can only do what you want with a direct SQL statement.
Even the original SQL statement should be executed within a transaction if you want to be sure no other changes can occur between reading and updating the value. It's one SQL statement, but the db still has to read the value, increment and store.

Entity Framework with OrderBy, Take and Skip can give incorrect results

So I want to return paged data from a query:
var data = context.MyTable.OrderByDescending(r => r.Field1)
.Skip(10)
.Take(10)
This will give me the second page of 10 rows order by Field1
But lets say all rows in the table have the same value for Field1, the data return by the Skip/Take is not correct. I've seen where the 2nd page may contain rows that where already returned in Page 1.
Note using EF 6.1.3
It would seem that to get the correct results, I need to ensure that the Ordering, results in a unique order of the data. So I add another column to the OrderBy, the Unique Id of the table.
var data = context.MyTable.OrderByDescending(r => r.Field1).ThenBy(r => r.FieldId)
.Skip(10)
.Take(10)
I've not found any documentation that confirms I need to do this, or is this a bug in EF?

Entityframework 6.2.0 IQueryable.Count VS IQueryable.ToList().Count

This is a very weird problem
In short
var q = (some query).Count();
Gives my a number and
var q = (some query).ToList().Count();
Gives me entirely different number...
with mentioning that (some query) has two includes (joins)
is there a sane explanation for that???
EDIT: here is my query
var q = db.membership_renewals.Include(i => i.member).Include(i => i.sport).Where(w => w.isDeleted == false).Count();
this gives me a wrong number
and this:
var q = db.membership_renewals.Include(i => i.member).Include(i => i.sport).Where(w => w.isDeleted == false).ToList().Count();
Gives me accurate number..
EDIT 2
Wher I wrote my query as linq query it worked perfectly...
var q1 = (from d in db.membership_renewals where d.isDeleted == false join m in db.members on d.mr_memberId equals m.m_id join s in db.sports on d.mr_sportId equals s.s_id select d.mr_id).Count();
I think the problem that entity framework doesn't execute the joins in the original query but forced to execute them in (ToList())...
I Finally figured out what's going on...
The database tables are not linked together in the database (there are no relationship or constraints defined in the database itself) so the code doesn't execute the (inner join) part.
However my classes on the other hand are well written so when I perform (ToList()) it automatically ignores the unbound rows...
And when I wrote the linq query defining the relation ship keys (primary and foreign) it worked alright because now the database understands my relation between tables...
Thanks everyone you've been great....
My guess is IQueryable gives a smaller number cause not all the objects are loaded, kind of like a stream in Java, but IQueryable.toList().count() forces the Iqueryable to load all the data and it is traversed by the list constructor and stored in the list so IQueryable.toList().Count() is the accurate answer. This is based on 5 minutes of search on MSDN.
The idea is the underlying datastore of the IQueryable is a database iterator so it executes differently every time because it executes the query again on the database, so if you call it twice against the same table, and the data has changed you get different results. This is called delayed execution. But when you say IQueryable.ToList() you force the iterator to do the whole iteration once and dump the results in a list which is constant

WCF Data services remove milliseconds from DateTime when expand

I get some strange behavior, when using WCF Data Services 5.6.
In my case, I have table, with 1 column set with Concurrency=Fixed, and this column hold date time field from database, updated each time when row is edited.
In case I just retrieve entity - this column has correct value with milliseconds. But if I do mapping - milliseconds are removed.
Here is a issue at glance :
====================================================================
void Main()
{
var b = from p in TABLE1 where p.ID == 100 select p;
b.Dump();
}
Request in this case is : http://xxxx/Data.svc/TABLE1(100M)
And data returned from service is :
<d:COL1 m:type="Edm.DateTime">2015-02-16T12:13:52.972</d:COL1>
====================================================================
As you can see , here time is returned with milliseconds - .972
In other case :
void Main()
{
var tmp = from p in TABLE1 where p.ID == 100 select
new TABLE1()
{
ID=p.ID,
COL1=p.COL1
};
var a1 = tmp.ToList();
a1.Dump();
}
Request in this case is : http://xxxx/Data.svc/TABLE1(100M)?$select=ID,COL1
<d:COL1 m:type="Edm.DateTime">2015-02-16T12:13:52</d:COL1>
====================================================================
Time is returned without milliseconds.
Does anybody have same problem? May be its a bug in the WCF Data services or in the model?
Ok, seems like I found an answer to this, or at least way to avoid the problem.
First I traced generated SQL from framework, and I see that in first case, im getting SQL
SELECT ID, COL1 FROM TABLE1
and in second case, I got
SELECT ID, CAST( COL1 AS DATETIME) FROM TABLE1
which cause the problem.
Then I tried to update EF to version 6, WCF Data services to version 5.6.3,
Oracle ODP to latest one, tried to use Oracle managed driver... no any success.
Then I played little bit with table definition, and I saw that my col1 with type TIMESTAMP in database and DateTime in the model was defined as NOT NULL.
If I remove this from database definition, I got right value with milliseconds.
So , may be this is a bug in Oracle driver, but probably this is a bug in the WCF Data Services. At least I found a way to use concurrency in my case with this solution.

MVC 3 Entity Framework 4.1 get a list of unique data rows

I am using MVC 3 and Entity Framework 4.1. I need to return a view that has a list of rows of DISTINCT values from my Documents database table. In SQL Server, the query that works is as follows:
SELECT DISTINCT(DocNum), Title, DocDate, DocFileName FROM Documents
How do I do the same thing in MVC 3?
var result = (from d in cntx.Documents
select d).Distinct();
Try:
var query = context.Documents.Select(x => new
{
x.DocNum,
x.Title,
x.DocDate,
x.DocFileName
}).Distinct().ToList();
Distinct must go over all returned columns otherwise you could end up with single DocNumber and for example multiple dates and query engine wouldn't know which date to select because only one record with given DocNumber can be returned.