EF 1.0 flattening a left join query - entity-framework

I'm trying to execute a linq to entites query in (Visual Studio 3.5 /EF 1.0) for 3 entities with the following relationships:
xcCRMCounterparty * => 0..1 CSIDsInUse
CSIDsInUse 1 => * xcCIFToCSID
Previously in T SQL I used:
select distinct CIF, xcCIFToCSID.xcCSID, CounterpartyName
from xcCIFToCSID
left join CSIDsInUse
on xcCIFToCSID.idCSID = CSIDsInUse.Id
left join xcCRMCounterparty
on CSIDsInUse.Id = xcCRMCounterparty.IdCSID
order by CounterpartyName
Now with EF I'm tried to flatten the result set as below, but I don't know how to flatten the xcCRMCounterparty item i.e. it's a collection rather than a single field
var query = from cifto in entities.xcCIFToCSIDSet.Include(x => x.CSIDsInUse).Include(x => x.CSIDsInUse.xcCRMCounterparty)
select new
{
cifto.CIF,
cifto.xcCSID,
cifto.CSIDsInUse.xcCRMCounterparty
};
How can I modify my query so that I can generate flattened results?

Try this:
var query = from cifto in entities.xcCIFToCSIDSet
from x in cifto.CSIDsInUse.xcCRMCouterparty
select new
{
cifto.CIF,
cifto.xcCSID,
x.Name
};

Related

Entity Framework Core Count unrelated records in another table

I need to count how many records in the tableA are not in the tableA, how to do this with LINQ?
with SQL I do the following way
select count(*) as total from produtoitemgrade g
where g.id not in (select idprodutograde from produtoestoque where idProduto = 12)
and g.idProduto = 12
my linq code so far.
var temp = (from a in Produtoitemgrades
join b in Produtoestoques on a.IdUnico equals b.IdUnicoGrade into g1
where g1.Count(y => y.IdProduto == 12)>0 && !g1.Any()
select a).ToList();
I tried to follow that example LINQ get rows from a table that don't exist in another table when using group by?
but an error occurs when running, how can I do this?
Thanks!
Your query should looks like the following, if you want to have the same SQL execution plan:
var query =
from a in Produtoitemgrades
where !Produtoestoques.Where(b => a.IdUnico == b.IdUnicoGrade && b.idProduto == 12).Any()
&& a.idProduto == 12
select a;
var result = query.Count();

EF core .any not filtering results

I have the following sql, which I'm trying to translate to linq:
SELECT *
FROM [Service] s
inner join vendor v on vendorid=v.id
inner join VendorLocation vl on vl.VendorId=v.id
where s.active=1 and v.active=1 and vl.City = 'toronto' and vl.Active=1
I have a Service that belongs to a Vendor and the Vendor has Locations. I'm trying to filter the locations based on city, but the query returns results that don't satisfy the conditions in the ".Any" clause
var service = await _context.Service
.Where(s => s.Active && s.Vendor.Active)
.Include(s => s.Vendor)
.ThenInclude(s => s.VendorLocations)
.Where(s => s.Vendor.VendorLocations.Any(l => l.City == City && l.Active))
.ToListAsync();
The sql statement returns the correct results but the linq is not.
Any help is appreciated, thanks! Ben
You can try with query notation:
var query = from v in _context.Vendors
join s in v.Services on v.Id equals s.VendorId
join l in v.ServiceLocations on v.Id equals l.VendorId
where v.Active && s.Active && l.City=="Toronto"
select new {v,s,l};
var result= await query.ToLinqAsync();
Hi your using EF Core now , But
I suggest Use LINQ because its simplest
Please read this page for more
and this is sample code
var innerGroupJoinQuery2 =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from prod2 in prodGroup
where prod2.UnitPrice > 2.50M
select prod2;
the query returns results that don't satisfy the conditions in the ".Any" clause
Those queries just aren't the same. The SQL Query returns one row per VendorLocation with additional columns from joined tables, and projects all the columns.
SELECT *
FROM [Service] s
inner join vendor v on vendorid=v.id
inner join VendorLocation vl on vl.VendorId=v.id
where s.active=1 and v.active=1 and vl.City = 'toronto' and vl.Active=1
In LINQ this would be something like
from vl in VendorLocation
where vl.Vendor.Active
&& vl.Vendor.Service.Active
&& vl.Active
&& vl.City = 'toronto'
select new
{
ServiceName = vl.Vendor.Service.Name,
ServiceDescription = vl.Vendor.Service.Description,
. . .
VendorName = vl.Vendor.Name,
VendorWhatever = vl.Vendor.Whatever,
. . .
vl.Name,
. . .
};

LINQ from objects Left Join

I have a linq query that works fine when I join two tables, but when I include another table, it does not return data. Please help me figure out what I am doing wrong.
First Linq returns data:
var q = (from c in _context.Complaint
join cl in _context.Checklist on c.COMP_ID equals cl.COMP_ID into clleft
from cls in clleft.DefaultIfEmpty()
orderby c.timestamp descending
select new
{
FileNum = c.FileNum
}).AsQueryable().Distinct();
return q;
When I add this table, no data returns
var q = (from c in _context.Complaint
join cl in _context.Checklist on c.COMP_ID equals cl.COMP_ID into clleft
from cls in clleft.DefaultIfEmpty()
join oim in _context.OIM_EMPLOYEE on cls.MonitorEnteredEmpID equals oim.EmpID into oimleft
from oims in oimleft.DefaultIfEmpty()
orderby c.timestamp descending
select new
{FileNum = c.FileNum
}).AsQueryable().Distinct();
return q;

The nested query is not supported: Entity Framework fails on grouped left joins

Consider this query:
from e in db.MyEntities
join o in db.MyOtherEntities
on new e.Foo equals o.Foo into others
from o in others.DefaultIfEmpty()
select new
{
Value1 = e.Value1,
Value2 = o.Value2
};
With this simple left join, Entity Framework fails on doing the following group
from e in query group e by new { } into g select g.Count()
That may seem obscure, but it's actually a common thing for automatic grid implementations to do with your queries.
I encountered this using DevExtreme's data library: Total summaries wouldn't work on queries with left joins.
What you get is a
NotSupportedException: The nested query is not supported. Operation1='GroupBy' Operation2='MultiStreamNest'
This works though:
from e in query.Take(1) select { Count = query.Count(), /* other aggregates */ }
And so does this:
from e in query group e by e.SomePropertyThatsActuallyConstant into g select g.Count()
There is a workaround. You can write your query like this:
from e in db.MyEntities
from o in db.MyOtherEntities.Where(o => o.Foo == e.Foo).DefaultIfEmpty()
select new
{
Value1 = e.Value1,
Value2 = o.Value2
};
Strangely it also works when you put a where clause after the join:
from e in db.MyEntities
join o in db.MyOtherEntities
on new e.Foo equals o.Foo into others
from o in others.DefaultIfEmpty()
where e.Value1 == e.Value1
select new
{
Value1 = e.Value1,
Value2 = o.Value2
};
The where clause condition must not be merely constants, I guess EF is smart enough to reduce it otherwise.

Entity framework: cross join causes OutOfMemoryException

I've got a table with 1.5 million records on a SQL Server 2008. There's a varchar column 'ReferenzNummer' that is indexed.
The following query executed in the SQL Management Studio works and is fast:
SELECT v1.Id, v2.Id FROM Vorpapier as v1 cross join Vorpapier as v2
WHERE v1.ReferenzNummer LIKE '7bd48e26-58d9-4c31-a755-a15500bce4c4'
AND v2.ReferenzNummer LIKE '7bd4%'
(I know the query does not make much sense like this, there will be more constraints, but that's not important for the moment)
Now I'd like to execute a query like this from Entity Framework 5.0, my LINQ looks like this:
var result = (from v1 in vorpapierRepository.DbSet
from v2 in vorpapierRepository.DbSet
where v1.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4" &&
v2.ReferenzNummer.StartsWith("7bd4")
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
This tries to load the whole table into memory, leading to an OutOfMemoryException after some time. I've tried to move the WHERE parts, with no success:
var result = (from v1 in vorpapierRepository.DbSet.Where(v => v.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4")
from v2 in vorpapierRepository.DbSet.Where(v => v.ReferenzNummer.StartsWith("7bd4"))
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
Is it possible to tell Entity Framework to create a cross join statement, like the one I've written myself?
UPDATE 1
The EF generated SQL looks like this (for both queries)
SELECT [Extent1].[Id] AS [Id],
[Extent1].[VorpapierArtId] AS [VorpapierArtId],
[Extent1].[ReferenzNummer] AS [ReferenzNummer],
[Extent1].[IsImported] AS [IsImported],
[Extent1].[DwhVorpapierId] AS [DwhVorpapierId],
[Extent1].[Datenbasis_Id] AS [Datenbasis_Id]
FROM [dbo].[Vorpapier] AS [Extent1]
UPDATE 2
When I change the LINQ query and join the table with itself on the field DatenbasisIDd (which is not exactly what I want, but it might work), EF creates a join:
var result = (from v1 in vorpapierRepository.DbSet
join v2 in vorpapierRepository.DbSet
on v1.DatenbasisId equals v2.DatenbasisId
where v1.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4" && v2.ReferenzNummer.StartsWith("7bd4")
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
The resulting SQL query looks like this. It works and is fast enough.
SELECT TOP (10) 1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1]
FROM [dbo].[Vorpapier] AS [Extent1]
INNER JOIN [dbo].[Vorpapier] AS [Extent2]
ON ([Extent1].[Datenbasis_Id] = [Extent2].[Datenbasis_Id])
OR (([Extent1].[Datenbasis_Id] IS NULL)
AND ([Extent2].[Datenbasis_Id] IS NULL))
WHERE (N'7bd48e26-58d9-4c31-a755-a15500bce4c4' = [Extent1].[ReferenzNummer])
AND ([Extent2].[ReferenzNummer] LIKE N'7bd4%')
I still don't see, why EF doesn't create the cross join in the original query. Is it simply not supported?
If you use a join in the linq statement it will get passed back to SQL Server. Here are some examples of the join operator in linq: http://code.msdn.microsoft.com/LINQ-Join-Operators-dabef4e9