Entity Framework and Linq-To-Entities are really giving me some headaches. I have a fairly simple query:
var result = feed.FeedItems.Any(ei => ei.ServerId == "12345");
feed is a single EF entity I selected earlier in a separate query from the same context.
But the generated SQL just throws away the .Any condition and requests all FeedItems of the feed object which can be several thousands of records which is a waste of Network bandwith. Seems the actual .Any comparison is done in C#:
exec sp_executesql N'SELECT [t0].[Id], [t0].[FeedId], [t0].[ServerId], [t0].[Published], [t0].[Inserted], [t0].[Title], [t0].[Content], [t0].[Author], [t0].[WebUri], [t0].[CommentsUri]
FROM [dbo].[FeedItem] AS [t0]
WHERE [t0].[FeedId] = #p0',N'#p0 int',#p0=3
I also tried:
!feed.FeedItems.Where(ei => ei.ServerId == "12345").Any();
But it doesn't change anything. Even removing Any() and querying for the complete list of items does not change the query.
I don't get it ... why isn't this working as I would expect? There should be a
WHERE ServerId == 1234
clause in the SQL statement.
Thanks very much for any help/clarification :)
As Nicholas already noticed, looks like query executed in FeedItems property (possibly you are returning List or IEnumerable) and whole list of items are returned from database. After that you are applying Any to in-memory collection. That's why you don't see WHERE ServerId == 1234 in SQL query.
When you apply Any to IQueryable generated query will look like:
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
[dbo].[FeedItem] AS [t0]
WHERE [t0].[ServerId] = #p0
) THEN 1
ELSE 0
END) AS [value]
Related
This worked in EF 6.4:
from a in Addresses
group a by new {a.StreetName, a.StreetNumber} into agrp
where agrp.Count() > 3
from aitem in agrp
select aitem
If EF Core 5 I get:
InvalidOperationException: The LINQ expression 'agrp => agrp' could
not be translated. Either rewrite the query in a form that can be
translated, or switch to client evaluation explicitly by inserting a
call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or
'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for
more information.
Why? Is there a different way to write this?
If you're OK with the data being loaded into memory, a simple solution could be to add .ToList() or .AsEnumerable() after Addresses:
from a in Addresses.ToList() // or .AsEnumerable()
group a by new {a.StreetName, a.StreetNumber} into agrp
where agrp.Count() > 3
from aitem in agrp
select aitem
Note that this (in SqlServer) translates into:
SELECT [a].[Id], [a].[StreetName], [a].[StreetNumber]
FROM [Addresses] AS [a]
In EF Core, GroupBy is (in many cases) not translated to SQL, but is run in memory.
(To avoid accidentally loading a lot of data into memory, EF will throw an exception unless .ToList() or .AsEnumerable() is called to indicate that this is intentional.)
(...) Since no database structure can represent an IGrouping, GroupBy operators have no translation in most cases. When an aggregate operator is applied to each group, which returns a scalar, it can be translated to SQL GROUP BY in relational databases. (...)
- Complex query operators, GroupBy
The article also has an example of a query which translates into group by with a filter on Count (included below).
The example doesn't fully cover the example in the question, unfortunately. It would not return the relevant Address-objects, only the group-by Key and Count.
var query = from p in context.Set<Post>()
group p by p.AuthorId into g
where g.Count() > 0
orderby g.Key
select new
{
g.Key,
Count = g.Count()
};
SELECT [p].[AuthorId] AS [Key], COUNT(*) AS [Count]
FROM [Posts] AS [p]
GROUP BY [p].[AuthorId]
HAVING COUNT(*) > 0
ORDER BY [p].[AuthorId]
This seems to work:
var addressGroupQuery = from a in Addresses
group a by new {a.StreetName, a.StreetType} into agrp
where agrp.Count() > 3
select agrp.Max(a => a.AddressID);
var addresses = from a in Addresses
where addressGroupQuery.Contains(a.AddressID)
select a;
Note the addressGroupQuery remains a deferred query (no ToList). Generates some clean looking SQL too:
SELECT [a].[AddressID], [a].[City], [a].[Country], [a].[StreetName], [a].[StreetNumber], [a].[StreetType], [a].[UnitNumber]
FROM [Address] AS [a]
WHERE EXISTS (
SELECT 1
FROM [Address] AS [a0]
GROUP BY [a0].[StreetName], [a0].[StreetType]
HAVING (COUNT(*) > 3) AND (MAX([a0].[AddressID]) = [a].[AddressID]))
I use spring data jpa with native query
I have already some query like this
How to use native query none parameter.
String q="SELECT t1.blockNumber-1 FROM someTAble t1 LEFT JOIN someTAble t2 ON t2.blockNumber = t1.blockNumber-1 WHERE t2.blockNumber IS NULL AND t1.blockNumber> 0 ORDER BY t1.blockNumber";
#Query(value = q,nativeQuery = true)
List<Entity> findByBlockNumberIs();
they are occur errors Column 'sequence' not found.
That query means are when i insert some Contiguous data int value then i find missing data.
But
this query working
SELECT *,t1.blockNumber-1 FROM someTAble t1 LEFT JOIN someTAble t2 ON t2.blockNumber = t1.blockNumber-1 WHERE t2.blockNumber IS NULL AND t1.blockNumber> 0 ORDER BY t1.blockNumber
The difference between the two queries is whether there is a '*' or not
how to change simple to my query.
How to i changed error
OR How to use spring data jpa predicate
QEntity qBe1= QEntity .blockEntity;
QEntity qBe2= QEntity .blockEntity;
build.and(qBe2.blockNumber.eq(be.getBlockNumber()-1))
.and(qBe2.blockNumber.isNull().and(qBe1.blockNumber.gt(0)));
is predicate can use left join?
well...
use this.
List<Integer> findByBlockNumber()
I have a fairly complex mysqli insert statement to do, as I need to gather data from two other tables and also use some variables available to me in php all in one statement.
It's confusing me because of the order of the variables for the prepared statements. - I am only inserting four values, but in order to get the values for t1 and t2, I am referencing these three additional variables too in the bind_param statement.
I should be populating jobRoleID,companyID,departmentID,competenceID with $newJobRoleID,$newCompanyID,t1.id,t2.id
$addJobCompetencies = $con->prepare("
INSERT INTO jobRoleCompetencies (jobRoleID,companyID,departmentID,competenceID)
WITH t1 AS (SELECT id FROM departments WHERE companyID = ? AND department = ?),
t2 AS (SELECT id FROM competencies WHERE companyID = ?)
SELECT ?,?,t1.id,t2.id FROM t1,t2");
if($addJobCompetencies) {
$addJobCompetencies->bind_param('isiii', $newCompanyID,$row['department'],$newCompanyID,$newJobRoleID,$newCompanyID);
$addJobCompetencies->execute();
} else {
echo $con->error;
}
$addJobCompetencies->free_result();
I am getting a syntax error but I'm not 100% sure why. Can anyone help?
Thanks
Dan
I haven't resolved the syntax issue with this query, but have got around it by simply combining the select statements to retrieve all the information I need in a single select statement...
SELECT ?,?,departments.id AS departmentID,competencies.id AS competencyID FROM departments,competencies... etc
Technology: EF 6.1.3, Database First Approach and SQL Server.
Issue: I'm facing an issue with the following Linq Query,
EmployeeEntities db = new EmployeeEntities();
IQueryable<Model.Employee> employees = from e in db.Employee
where e.EmployeeName == null
select e;
I'm trying to get employees whose EmployeeName is Null but I'm not getting any records, whereas when I query in the database (SQL Server), I'm getting the results properly.
I suspect the linq query is not converting where clause as EmployeeName IS NULL but it simply converts like EmployeeName == null.
Please let me know how to fix this issue..
Thanks,
Prakash.
You need to call ToList() to materialize the query. EF will definitely convert to the proper operator in SQL.
So the code becomes:
List<Model.Employee> employees = (from e in db.Employee
where e.EmployeeName == null
select e).ToList();
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.