Linq to Entities count not returning results - entity-framework

I have the following linq query that is producing the wrong sql (ProductId = PictureId). We just switched over to using Devart Entity Developer to auto-generate our POCO classes and this issue popped up. The mapping looks correct to me and this query returned the correct results previously. Does the mapping look wrong or perhaps the query itself was never correct?
Using Entity Framework 5.0.
Query:
var totalResults = _productRepository.Table.Where(a => a.Pictures.Any()).Count();
SQL:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Product] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[ProductPicture] AS [Extent2]
WHERE [Extent1].[ProductId] = [Extent2].[PictureId] // this should be ProductId = ProductId
)
) AS [GroupBy1]
Fluent Mapping:
modelBuilder.Entity<Picture>()
.HasMany(p => p.Products)
.WithMany(c => c.Pictures)
.Map(manyToMany => manyToMany
.ToTable("ProductPicture", "dbo")
.MapLeftKey("ProductId")
.MapRightKey("PictureId"));
Diagram:

The bug with association mapping in the DbContext template is fixed in the latest (5.7.276) build of Entity Developer: http://forums.devart.com/viewtopic.php?f=32&t=28723.

Related

How to write subquery in select list in EF Core?

Select *,
(Select DefaultStartDay from Scheduler.ProgramSettings ps where ps.DefaultStartDay = s.Id ) [DefaultStartDay]
from Scheduler.Schedules s
where ScheduleType = 2;
I want to write above SQL query in EF Core, Specially I need subquery in select list to get data from another table with specific condition.
please refer image.Sample Data with SQL Query
I have tried below EF Core but getting wrong result.
var model = _context.Schedules
.Where(s => s.ScheduleType == 2)
.Select(rv => new ProgramSetting
{
Id = rv.Id,
ProgramTemplateId = rv.ProgramTemplateId,
IsActive = rv.IsActive,
DefaultStartDay = rv.Id
}).ToArray();
The SQL query is wrong and this is a misuse of EF Core.
First, that SQL will fail if there's more than 1 result from the subquery. Even in SQL you'd need a different query. An INNER JOIN would return the same results without failing if there are multiple matches.
Select s.*,ps.DefaultStartDay
from Scheduler.Schedules s
inner join Scheduler.ProgramSettings ps on ps.DefaultStartDay = s.Id
where ScheduleType = 2;
Second, using LINQ to emulate SQL is a misuse of both EF Core and LINQ. EF isn't a replacement for SQL, it's an ORM. Its job is to give the impression of working with in-memory objects instead of tables, not allow you to write SQL queries in C#
It's the ORM's job to generate JOINs as needed from the relations between entities (not tables). In this case, if Schedule has a ProgramSettins property, EF would generate the necessary joins automatically. Loading an entire schedule object could be as simple as :
var schedules=_context.Schedules
.Incule(sch=>sch.ProgramSettings)
.Where(s => s.ScheduleType == 2)
.ToArray();
Include is used to eagerly load the settings, not to force a JOIN.
If a Select clause is used that requires a property from ProgramSettings, the JOIN will be generated automatically, eg :
var namesAndDays=_context.Schedules
.Where(s => s.ScheduleType == 2)
.Select(s=>new {
Name = s.Name,
StartDay = s.ProgramSettings.DefaultStartDay
})
.ToArray();

Select with fields to include in detail table with EF Core

How can I select whitch fields should be included for detail table in EF Core.
I tried with this query:
var result= this.context.MainTable
.Include(t => t.DetailTable)
.Select(t => new {
id = t.Id,
values = t.DetailTable.Select(t2 => t2.SomeField)
})
.ToArray();
I would expect this result to single query, but it does not. It automatically execute query one by one for every row in MainTable and select SomeField.

Entity Framework LINQ Query match all members of child collection

I have a Site table that has a many-to-many relationship with a UtilityServiceConnection table using a linking table called LinkSiteUtilityServiceConnection. Given a set of ServiceConnectionIds, I need to locate the Site that is exclusively linked to all of them and no more. I think I should be able to write the query using All on the collection but it's not working as expected.
var serviceConnectionIds = new[] { 546892, 546911, 546923 };
var sites1 = db.Sites
.Where(x => x.LinkSiteUtilityServiceConnections.All(y => serviceConnectionIds.Contains(y.UtilityServiceConnectionId)))
.ToList();
Assert.AreEqual(1, sites1.Count); //fails
This produces the query below that returns ~250,000 records when I expect to get one.
SELECT [Extent1].*
FROM [dbo].[Site] AS [Extent1]
WHERE NOT EXISTS (SELECT 1 AS [C1]
FROM [dbo].[LinkSiteUtilityServiceConnection] AS [Extent2]
WHERE ([Extent1].[SiteId] = [Extent2].[SiteId])
AND ((NOT ([Extent2].[UtilityServiceConnectionId] IN (546892, 546911, 546923)))
OR (CASE
WHEN ([Extent2].[UtilityServiceConnectionId] IN (546892, 546911, 546923)) THEN cast(1 as bit)
WHEN (NOT ([Extent2].[UtilityServiceConnectionId] IN (546892, 546911, 546923))) THEN cast(0 as bit)
END IS NULL)))
Why isn't All working as I expect? What's the best way to write this query?
check this code:
query 1:
var sites1 = db.Sites
.Where(x => serviceConnectionIds.All(y =>
x.LinkSiteUtilityServiceConnections
.Select(u => u.UtilityServiceConnectionId).Contains(y)))
.ToList();
query 2:
var query = db.Posts.AsQueryable();
var sites1 = serviceConnectionIds.Aggregate(query,
(current, item) => current.Where(e => e.LinkSiteUtilityServiceConnections
.Any(c => c.UtilityServiceConnectionId== item))).ToList();

EF 7 - Navigation properties - incorrect SQL?

Does EF7 fully support navigation properties and custom projection? Or maybe I'm misunderstanding how to construct this query. The Study entity has a nullable ProjectId and corresponding virtual Project navigation property. The Project entity has a non-nullable CategoryId and Category navigation property. The entities were reverse scaffolded using the ef command.
If I run the following query:
return _context.Study
.Include(s => s.Project)
.ThenInclude(p => p.Category)
.Select(s => new Models.StudySearchResult
{
StudyId = s.StudyId,
MasterStudyId = s.MasterStudyId,
ShortTitle = s.ShortTitle,
Category = s.Project == null ? string.Empty : s.Project.Category.CategoryDesc,
SubmitterId = s.SubmitterId
}).ToList();
EF7 incorrectly generates the following SQL, which uses INNER JOIN instead of LEFT JOIN:
SELECT [s].[StudyId]
,[s].[MasterStudyId]
,[s].[ShortTitle]
,CASE WHEN [s].[ProjectId] IS NULL THEN #__Empty_0 ELSE [s.Project.Category].[CategoryDesc] END
,[s].[SubmitterId]
FROM [Study] AS [s]
INNER JOIN [Project] AS [s.Project]
ON [s].[ProjectId] = [s.Project].[ProjectId]
INNER JOIN [Category] AS [s.Project.Category]
ON [s.Project].[CategoryId] = [s.Project.Category].[CategoryId]
I have the same problem. And I found out that there is currently open issue in EF7 for generating SQL for optional navigations. It will be fixed in RC2.
https://github.com/aspnet/EntityFramework/issues/4205
https://github.com/aspnet/EntityFramework/issues/3186

Getting the *complete* SQL query generated by Entity Framework when specifying a variable at runtime?

I know that I can simply use ToString() to see the SQL statement generated by EF. But how can I get the SQL when I am using a variable in my statement? In the following aType and bVal are each variables.
var foo = context.PUBooleanAttributes
.Where(u => u.PUAttributeID == aType && u.Value == bVal)
.Select(abc => abc.User);
which generates the following:
{SELECT
[Extent2].[UserID] AS [UserID],
[Extent2].[Email] AS [Email],
[Extent2].[GUID] AS [GUID]
FROM [dbo].[PUBooleanAttributes] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserID] = [Extent2].[UserID]
WHERE ([Extent1].[PUAttributeID] = #p__linq__0) AND ([Extent1].[Value] = #p__linq__1)}
What I'd like to see is the actual values supplied at runtime instead of #p__linq__0