My sql query is
SELECT DISTINCT
tblProjects.RevID, tblProjects.CEQRNum, tblProjects.ProjectName, GEOCODE.BBL, tblProjects.BoroID, GEOCODE.BLOCK, GEOCODE.LOT,
tblMilestoneType.MilestoneName, tblMilestone.MilestoneDate
FROM tblMilestoneType INNER JOIN
tblMilestone ON tblMilestoneType.MilestoneID = tblMilestone.MilestoneTypeID RIGHT OUTER JOIN
tblProjects ON tblMilestone.RevID = tblProjects.RevID LEFT OUTER JOIN
GEOCODE ON tblProjects.RevID = GEOCODE.RevID
WHERE (
tblMilestone.MilestoneDate IN (SELECT MAX(tblMilestone.MilestoneDate) AS MilestoneDate
FROM tblMilestone INNER JOIN tblMilestoneType ON tblMilestone.MilestoneTypeID = tblMilestoneType.MilestoneID
GROUP BY tblMilestone.RevID)
)
ORDER BY tblProjects.RevID
I am trying to convert this to linq.
So i started with
projectList = db.tblMilestoneTypes
.Join(db.tblMilestones,
mileType => mileType.MilestoneID,
mile => mile.MilestoneTypeID,
(mileType, mile) => new
{
tblMilestoneType = mileType,
tblMilestone = mile
})
.Join(db.tblProjects,
project => project. // does not work)
Also tried
projectList = from MilestoneTypeTable in db.tblMilestoneTypes
join MilestoneTable in db.tblMilestones on MilestoneTypeTable.MilestoneID equals MilestoneTable.MilestoneTypeID
rig // no right or left join.
How do i do this
Neha
You can try
projectList = from MilestoneTypeTable in db.tblMilestoneTypes
join MilestoneTable in db.tblMilestones on MilestoneTypeTable.MilestoneID equals MilestoneTable.MilestoneTypeID into MileStones
from mileStone in MileStones
join from projects in db.tblProjects
on mileStone.RevID equals projects.RevID
select new { MileStoneType = MilestoneTypeTable, MileStones = mileStone , Project = projects };
Well After a lot of R&D This is what I found out
the T-SQL with LEFT OUTER JOIN and RIGHT OUTER JOIN can be converted to one query with only LEFT OUTER JOIN
put subquery as a part of join
and here is the query.
var query = from ProjectTable in db.tblProjects
from GeoCodeTable in db.GEOCODEs.Where(geo => geo.RevID == ProjectTable.RevID).DefaultIfEmpty()
from MilestoneTable in db.tblMilestones.Where(mile => mile.RevID == GeoCodeTable.RevID && mile.MilestoneDate == db.tblMilestones.OrderBy(x => x.RevID).Select(x => x.MilestoneDate).Max()).DefaultIfEmpty()
from MilestomeTypeTable in db.tblMilestoneTypes.Where(mt => mt.MilestoneID == MilestoneTable.MilestoneTypeID).DefaultIfEmpty()
select new
{
Milestone = MilestoneTable,
Project = ProjectTable,
GeoCode = GeoCodeTable,
MilestomeType = MilestomeTypeTable
};
Related
I have the following SQL query which is returning one row of data exactly as expected:
select count(c.ID) as NoteCount, count(s.ClaimStatusHistoryID) as ActionCount, p.DayGoal
from Collector_Profile p
left join ClaimStatusHistory s on s.AppUserID = p.AppUserID and CONVERT(varchar(10), s.StatusDateTZ, 101) = convert(varchar(10), GETDATE(), 101)
left join Claim_Notes c on c.CollectorID = p.ID and CONVERT(varchar(10),c.PostDateTZ,101) = convert(varchar(10), GETDATE(), 101)
where p.ID = 1338
group by p.DayGoal
I am trying to convert to LINQ. When I attempt to include the DbFunctions.TruncateTime, I get an error that TruncateTime is not defined. So I have commented them out in this example, but I need to get that working as well. This is what I have so far, which compiles but throws an error:
var utcNow = DateTimeOffset.UtcNow.Date;
var query = from p in _context.Collector_Profile
join s in _context.ClaimStatusHistory on p.AppUserID
equals s.AppUserID into gs
// && DbFunctions.TruncateTime(s.StatusDateTZ) equals utcNow into gs
join c in _context.Claim_Notes on p.ID
equals c.CollectorID into gc
//&& DbFunctions.TruncateTime(c.PostDateTZ) equals utcNow into gc
from s in gs.DefaultIfEmpty()
from c in gc.DefaultIfEmpty()
where p.ID == CollectorID
group new { gs, gc } by p.DayGoal into grouped
select new UserStatistics { DayGoal = grouped.Key,
NoteCount = grouped.Count(x => x.gc.Any()),
ActionCount = grouped.Count(x => x.gs.Any()) };
return query.FirstOrDefault();
I get the following error when I run it:
InvalidOperationException: Processing of the LINQ expression 'DbSet<Collector_Profile>
.GroupJoin(
outer: DbSet<ClaimStatusHistory>,
inner: p => p.AppUserID,
outerKeySelector: s => s.AppUserID,
innerKeySelector: (p, gs) => new {
p = p,
gs = gs
})' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
Can someone help me to get this linq query working? Thanks for any assistance and examples. I've looked at lots of questions and none are doing exactly what I'm doing that I've found yet.
I believe this should work, barring issues with DateTimeOffset.Date and timezones.
Since EF Core 3 only has extremely limited support for translating GroupJoin (basically just to LEFT JOIN), you must split the query into two parts, a SQL query with LEFT JOIN and then a client side GroupBy to create the effect of GroupJoin.
var utcNowDate = DateTimeOffset.UtcNow.Date;
var dbQuery = from p in _context.Collector_Profile
where p.ID == CollectorID
join s in _context.ClaimStatusHistory.Where(s => s.StatusDateTZ.Value.Date == utcNowDate) on p.AppUserID equals s.AppUserID into gs
from s in gs.DefaultIfEmpty()
join c in _context.Claim_Notes.Where(c => c.PostDateTZ.Value.Date == utcNowDate) on p.ID equals c.CollectorID into gc
from c in gc.DefaultIfEmpty()
select new { p.DayGoal, s = s.ClaimStatusHistoryID, c = c.ID };
var query = from psc in dbQuery.AsEnumerable()
group new { psc.s, psc.c } by psc.DayGoal into grouped
select new UserStatistics {
DayGoal = grouped.Key,
NoteCount = grouped.Count(sc => sc.c != null),
ActionCount = grouped.Count(sc => sc.s != null)
};
return query.FirstOrDefault();
I use Amazon Lambda which has memory limits for proceeding certain actions. And this query retrieving quite a lot of data (~100k+ rows) and running out of those limits.
SELECT EE.ID, ILE.Zip AS EventLocationZip, EET.Name as EventType, EE.TypeID as EventTypeID, E.Length, EL.Name as LengthUnit,
CP.Name as EventPlaceName, EE.FKPlaceID as EventPlaceID, IL.Name as EventLocationName, IL.ID as EventLocationId,
I.ID as InstituteID, I.Name as InstituteName, I.Email, I.Telephone, I.FAX, ILA.City, ILA.Zip, ILA.Street, ILA.Country,
E.ID as EducationID, E.Name as EducationName, E.Link as EducationLink, CE.Name as EducationTypeName, CE.ID as EducationTypeID,
ESI.TypeID as EventStartInfoTypeID, ESI.Date as StartDate, ESI.EndDate, ESI.Month, ESI.MonthYear, ESI.FKSemesterID as Semester, ESI.SemesterYear,
EEP.Vat, EEP.Price, EC.Name as Currency, IP.Value as TextPropertyValue, IP.FKTextPropertyID as TextPropertyID, CPIL.Name AS EventLocationPlaceName,
CPIL2.Name AS EventLocationPlaceNameParent
FROM
education.EducationEvents EE
INNER JOIN education.EventStartInfos ESI ON EE.ID = ESI.FKEducationEventID
INNER JOIN education.EducationEventPrices EEP ON EE.ID = EEP.FKEventID
INNER JOIN education.TypeOfEvents EET ON EE.TypeID = EET.ID
LEFT JOIN institute.InstituteLocations IL ON IL.ID = EE.FKLocationID
LEFT JOIN core.Places CPIL ON CPIL.ID = IL.FKPlaceID
LEFT JOIN core.Places CPIL2 ON CPIL2.ID = CPIL.FKParentID
LEFT JOIN institute.LocationAddresses ILE ON ILE.ID = IL.FKVisitingAddressID
LEFT JOIN core.Places CP ON CP.ID = EE.FKPlaceID
INNER JOIN economy.Currencies EC ON EEP.FKCurrencyID = EC.ID
INNER JOIN education.Educations E ON EE.FKEducationID = E.ID
LEFT JOIN education.LengthUnits EL ON E.FKLengthUnitID = EL.ID
INNER JOIN core.EducationTypes CE ON CE.ID = E.FKEducationTypeID
INNER JOIN institute.Institutes I ON E.FKInstituteID = I.ID
LEFT JOIN institute.InstituteTextProperties IP ON IP.FKInstituteID = I.ID
INNER JOIN institute.LocationAddresses ILA ON ILA.ID = I.FKMainAddressID
INNER JOIN searchIndex.IndexInstitutes II ON I.ID = II.FKInstituteID
INNER JOIN searchIndex.IndexEducations IE ON E.ID = IE.FKEducationID AND II.FKIndexID = IE.FKIndexID
WHERE
II.FKIndexID = #IndexID AND I.IsPublished = 1 AND ESI.Description IS NULL AND (IP.FKTextPropertyID = 1 OR IP.FKTextPropertyID IS NULL)
ORDER BY I.ID DESC
Using Entity framework. Extension:
public static class DbContextExtensions
{
public static async Task<IReadOnlyList<T>> FromSql<T>(this DbContext context, string sql, params object[] parameters) where T : class
{
return await context.Set<T>().FromSql(sql, parameters).AsNoTracking().ToListAsync().ConfigureAwait(false);
}
}
And usage:
var data = await _context.FromSql<Model>("Query string", parameter);
What would be the best permanent solution for optimizing particular query? Thank you for the answers
Good day! I need transform join to left join in my query -
var query = (from sections in context.Sections
join themes in context.Themes on sections.SectionId equals themes.SectionId
join comments in context.Comments on themes.ThemeId equals comments.ThemeId
select new { sections.SectionId, sections.SectionTitle, themes.ThemeId, comments.CommentId } into x
group x by new { x.SectionId, x.SectionTitle } into g
select new SectionInfo
{
SectionId = g.Key.SectionId,
SectionTitle = g.Key.SectionTitle,
ThemeCount = g.Select(s => s.ThemeId).Count(),
CommentCount = g.Select(s => s.CommentId).Count()
}).ToList();
- please, i have no idea(
You need to use DefaultIfEmpty
One way is like this:
from themes in context.Themes.Where(x => sections.SectionId == x.SectionId)
.DefaultIfEmpty()
Alternate way
join themes in context.Themes on sections.SectionId equals themes.SectionId into themesGroup
from themes in themesGroup.DefaultIfEmpty()
I am struggling with how to write the below equivalent as LINQ. Truly I guess I am only struggling with how I represent the INNER JOIN () portion. Is that called a Nested Join? Anonymous Join? I am not even sure. Anyway, big thanks to anyone who can point me true. Even if it is just what this is called so I can BING it properly.
SELECT p.PersonID, p.FirstName, p.MiddleName, p.LastName, cp.EnrollmentID, cp.EnrollmentDate, cp.DisenrollmentDate
FROM vwPersonInfo AS p
INNER JOIN (
SELECT c.ClientID, c.EnrollmentID, c.EnrollmentDate, c.DisenrollmentDate
FROM tblCMOEnrollment AS c
LEFT OUTER JOIN tblWorkerHistory AS wh
ON c.EnrollmentID = wh.EnrollmentID
INNER JOIN tblStaffExtended AS se
ON wh.Worker = se.StaffID
WHERE (wh.EndDate IS NULL OR wh.EndDate >= getdate())
AND wh.Worker = --WorkerID Param Here
) AS cp
ON p.PersonID = cp.ClientID
ORDER BY p.PersonID
just put the inner query in its own variable. (It will be translated into one single SQL expression)
var innerQuery = from x in db.tblCMOEnrollment
where ...
select ...;
var query = from a in vwPersonInfo
join b innerQuery on p.PersonID equals cp.ClientID
select ...;
I think you can do this by writing a second method and joining on that method:
private static IEnumerable<Table> GetData(int joinKey)
{
return (from x in context.TableB.Where(id => id.Key == joinKey select x).AsQueryable();
}
Then you can do your normal query:
var query = from c in context.TableA
join GetData(c.PrimaryKeyValue)
I have a beginners LINQ2SQL question. I have this huge (but not complex) SQL statement:
SELECT Artikel.ArtikelID,
Artikel.CategorieID,
Artikel.ImageFile,
Artikel.RetailPrijs,
ISNULL(ShopArtikel.VerkoopsPrijs, Artikel.VerkoopsPrijs) AS VerkoopsPrijs,
Artikel.ArtikelCode,
Artikel.InAssortimentSinds,
ArtikelTaal.ArtikelNaam,
ArtikelTaal.ArtikelOmschrijving
FROM Artikel
INNER JOIN ArtikelTaal ON Artikel.ArtikelID = ArtikelTaal.ArtikelID
INNER JOIN ShopArtikel ON Artikel.ArtikelID = ShopArtikel.ArtikelID
INNER JOIN Categorie ON Artikel.CategorieID = Categorie.CategorieID
INNER JOIN CategorieTaal ON Categorie.CategorieID = CategorieTaal.CategorieID
INNER JOIN Shop ON ShopArtikel.ShopId = Shop.ShopID
INNER JOIN CategorieGroepShop ON Shop.ShopID = CategorieGroepShop.ShopId
INNER JOIN Taal ON ArtikelTaal.TaalCode = Taal.TaalCode AND CategorieTaal.TaalCode = Taal.TaalCode
INNER JOIN CategorieGroepTaal ON Taal.TaalCode = CategorieGroepTaal.TaalCode AND CategorieGroepShop.CategorieGroepId = CategorieGroepTaal.CategorieGroepID
INNER JOIN CategorieGroep ON Categorie.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepTaal.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepShop.CategorieGroepId = CategorieGroep.CategorieGroepID
WHERE (Shop.ShopID = 23) AND
(Taal.TaalCode = 'dut') AND
(Artikel.Onzichtbaar = 0) AND
(Artikel.NietBestelbaar = 0) AND
(Categorie.Onzichtbaar = 0) AND
(Artikel.Voorraad >= Artikel.LevertijdDrempel)
and I am converting this to LINQ and have this:
var allProducts = from artikelen in dc.Artikels
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join catg in dc.CategorieGroeps on cat.CategorieGroepID equals catg.CategorieGroepID
join catgt in dc.CategorieGroepTaals on catg.CategorieGroepID equals catgt.CategorieGroepID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catgt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
where sh.ShopID == shop.BLL.Business.ShopController.CurrentShop.Id
select dc.Artikels;
but I have the idea that I made some (minor) mistakes while joining.
any ideas please!
EDIT
I have rewritten the LINQ query to this:
var allProducts = from artikelen in dc.Artikels
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
join catgt in dc.CategorieGroepTaals on new { tl.TaalCode, catgs.CategorieGroepId } equals new { catgt.TaalCode, catgt.CategorieGroepID }
join catg in dc.CategorieGroeps on new { cat.CategorieGroepID, catgt.CategorieGroepID, catgs.CategorieGroepId } equals new { catg.CategorieGroepID, catg.CategorieGroepID, catg.CategorieGroepID }
where sh.ShopID == 230
select dc.Artikels;
but I have a syntax error after "dut" }
Edit 2:
changed the join and replaced "dut" with the corresponding field in the database.
still have the error after the first }
it says: type inference failed in the call to 'Join'
Some of the SQL joins have multiple join conditions, which you didn't put in the LINQ query.
If this is something that will be frequently run then you should rewrite it as a stored procedure. I believe it is too convoluted and complex for a LINQ statement - too hard to see what's going on.
There is a tool for it, but I didn't try it. May be it's usefull for you.
http://www.sqltolinq.com/
It looks like the error line is actually a "Where" cause but not "Joining".
You can actually split the whole long Linq statement into smaller Query.
so for this case, its better to split it like this:
var at = from a in dc.ArtikelTaals
where a.TaalCode == "dut"
select a;
var catt = from c in dc.CategorieTaals
where c.TaalCode == "dut"
select c;
.....
and you can join the IQueryable "at" and "catt" in your complex query later.