Convert SQL to LINQ/EF - sql

I want to convert this SQL query to LINQ. But I'm new in EF. Please help
SQL Query
select * from VersionHistory where id in( select OptionsId from StylesHistory where ConId=540 and OptionsId = 28286 and ModifiedAtVersion>1)
TIA
I tried Something like this
var stylesHistory = _context.VersionHistory
.Where(x => x.ModifiedAtVersion > 1
&& x.Id==28286
&& x.Contract.Id==540)
.ToList()
Not Sure How I can add Sub Query

You can easily write that as:
var result = ctx.VersionHistory
.Where(vh => ctx.StylesHistory
.Any( sh => sh.OptionsId == vh.Id &&
sh.OptionsId == 28286 &&
sh.ConId = 540 &&
sh.ModifiedAtVersion > 1));

You can also create your subquery as another IEnumerable which you'll use in the main query.
This will improve readibility.
EF will only generate one query.

Related

I have a SQL query and I want to convert it to linq

I have a SQL query which I want to convert to Linq.
This is my SQL query:
SELECT
Calisanlar.CalisanId,
CovidYakalanmaTarih,
CovidBitisTarih
FROM
Calisanlar
INNER JOIN
Covids ON Calisanlar.CalisanId = Covids.CalisanId
WHERE
Calisanlar.CalisanId IN (SELECT TOP 10 CalisanId
FROM Hastaliklar
GROUP BY CalisanId
ORDER BY COUNT(*) DESC)
AND DATEDIFF(DAY, CovidYakalanmaTarih, GETDATE()) BETWEEN 0 AND 30
I wrote this C# code, but it doesn't work as expected because i didn't write "DATEDIFF(DAY, CovidYakalanmaTarih, GETDATE()) BETWEEN 0 AND 30" linq version:
var query = context.Hastaliklar
.GroupBy(x => x.CalisanId)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(10)
.ToList();
var result = from hastalik in context.Hastaliklar
join covid in context.Covids
on hastalik.CalisanId equals covid.CalisanId
where query.Contains(hastalik.CalisanId)
&& EF.Functions.DateDiffDay(covid.CovidYakalanmaTarih, covid.CovidBitisTarih)
select new SonBirAyCovidDto
{
CalisanId = covid.CalisanId,
CovidYakalanmaTarih = covid.CovidYakalanmaTarih,
CovidBitisTarih = covid.CovidBitisTarih
};
There is not direct translation to BETWEEN in EF Core, but you can make other condition. Also it is better to remove ToList() from first query, in this case you will have only one roundtrip to database.
var query = context.Hastaliklar
.GroupBy(x => x.CalisanId)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(10);
var result =
from hastalik in context.Hastaliklar
join covid in context.Covids
on hastalik.CalisanId equals covid.CalisanId
where query.Contains(hastalik.CalisanId)
&& covid.CovidYakalanmaTarih <= covid.CovidBitisTarih
&& EF.Functions.DateDiffDay(covid.CovidYakalanmaTarih, covid.CovidBitisTarih) <= 30
select new SonBirAyCovidDto
{
CalisanId = covid.CalisanId,
CovidYakalanmaTarih = covid.CovidYakalanmaTarih,
CovidBitisTarih = covid.CovidBitisTarih
};

Linq to SQL combination of aggregate functions

Is there a way to simplify this and make it go faster?
In SQL I use count(*) and count(distinct) in same query which gives me a faster result
Thanks a bunch.
int numberOfUsers = (from u in db.UseLogs
where u.DocID == docID
&& u.LogDate >= fromDate
&& u.LogDate <= to
select u.UserID).Distinct().Count();
int numberOfVisits = (from u in db.UseLogs
where u.DocID == docID
&& u.LogDate >= fromDate
&& u.LogDate <= to
select u).Count();
Conclusion
There is no Count( Distinct) in LINQ. Not EVERY SQL statement can be translated into LINQ.
Thanks for the help guys!
Is this what you're looking for?
from u in db.UseLogs
where u.DocId == docId && u.LogDate >= fromDate && u.LogDate <= to
group u by true into g
select new
{
Count = g.Count(),
DistinctUserCount = g.Select(x => x.UserId).Distinct().Count()
}
You will want to check if it's actually faster than running two queries, or if the performance gain is worth the loss of readability.
Not exactly what you're trying to acheive but may be just as fast:
var query =
from u in db.UseLogs
where u.DocId == docId && u.LogDate >= fromDate && u.LogDate <= to
group u by u.UserID into g
select new
{
Visits = g.Count()
};
int numberOfUsers = query.Count();
int numberOfVisits = query.Sum(q=>q.Visits);
It executes the SQL only once and does the SUMming in memory.

How to convert this SQL to LINQ or Lambda expression?

here's my sql query below:
Can you guys help me to convert this to a much cleaner one??
SELECT [PurchaseRequestID], [ProjectID],[FullName]
FROM PurchaseRequest
WHERE [PurchaseRequestID] IN
(SELECT [PurchaseRequestID] FROM PurchaseRequestDetail )
AND [PurchaseRequestID] NOT IN
(SELECT [PurchaseRequestID] FROM [PurchaseOrder] )
Though i have already converted this successfuly, i think this is not readable and needs to be rewritten:
var query = from a in db.PurchaseRequests
where
(from b in db.PurchaseRequestDetails
select new
{
b.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID }) &&
!(from c in db.PurchaseOrders
select new
{
c.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID })
select a;
thanks
you really don't need all those anonymous objects. Use the let keyword to introduce temporary variables instead of doing operations on the subqueries directly.
from a in db.PurchaseRequests
let b = from b in db.PurchaseRequestDetails select b.PurchaseRequestID
let c = from c in db.PurchaseOrders select c.PurchaseRequestID
where b.Contains(a.PurchaseRequestID) && !c.contains(a.PurchaseRequestID)
select a;
var query = from a in db.PurchaseRequests
where
db.PurchaseRequestDetails.Any(x => x.PurchaseRequestID == a.PurchaseRequestID) &&
!db.PurchaseOrders.Any(x => x.PurchaseRequestID == a.PurchaseRequestID)
select a;
If you have navigation properties set up, you can write the query like this:
IQueryable<PurchaseRequest> query =
from purchaseRequest in myDataContext.PurchaseRequests
where purchaseRequest.PurchaseRequestDetail.Any()
where !purchaseRequest.PurchaseOrder.Any()
select purchaseRequest;
Or this lambda/method style if you prefer...
IQueryable<PurchaseRequest> query2 = myDataContext.PurchaseRequests
.Where(purchaseRequest => purchaseRequest.PurchaseRequestDetail.Any())
.Where(purchaseRequest => !purchaseRequest.PurchaseOrder.Any());

Nested selects in LINQ expression, how to?

I don't know how to work with nested selects in LINQ.
How could I convert this SQl expression to LINQ?
Select i.ID, i.Impression,
(Select COUNT(ImpressionsId)
from DiaryImpressions
where DiaryPostsId = '2' AND ImpressionsId = i.ID) as Num from Impressions i
Seriously? DiaryPostsId is a string? Oh well...
from i in context.Impressions
select new {
i.ID,
i.Impressions,
Num = (from d in context.DiaryImpressions
where d.DiaryPostsId == "2"
&& d.ImpressionsId == i.ID
select d).Count()
}
from ...
select new {
i.Id,
i.Impression,
Count = context.DiaryImpressions.Count(d => d.DiaryPostsId == 2 && d.ImpressionsId == i.Id)
}
If you map your objects properly, you can use child relations directly:
Count = i.DiaryImpressions.Count(d => d.DiaryPostsId == 2)

Entity Framework and dynamic order by statements

I have been struggling to get this working. I wish to have an EF statement take in a column to order by. My original statement was this:
var Query = from P in DbContext.People
where P.BusinessUnits.Any(BU =>BU.BusinessUnitID == businessUnitId)
orderby P.LastName
select P;
And I changed this to the following:
var Query = from P in DbContext.People
where P.BusinessUnits.Any(BU =>BU.BusinessUnitID == businessUnitId)
orderby sortField
select P;
Where sortField is the column we wish to sort on, and is a string i.e. LastName. However, it does not appear to work, it does no sorting, and the outputted SQL string is completely wrong. Anyone got this working before?
you could try passing in an expression to your method with the following type:
Expression<Func<Person, object>> expr = p => p.LastName;
and then using linq extensions instead of linq expressions...
var Query =
DbContext.People
.Where(P => P.BusinessUnits.Any(BU =>BU.BusinessUnitID == businessUnitId))
.OrderBy(expr)
.ToList();
Your sort does not work because you are sorting on a string literal. It is not illegal, but it is not particularly useful either. You need to provide a sorting field through the API of IQueryable<T>, for example, like this:
var q = from P in DbContext.People
where P.BusinessUnits.Any(BU =>BU.BusinessUnitID == businessUnitId)
orderby P.LastName
select P;
if ("sortField".Equals("FirstName"))
q = q.OrderBy(p => p.FirstName);
else if ("sortField".Equals("LastName"))
q = q.OrderBy(p => p.LastName);
else if ("sortField".Equals("Dob"))
q = q.OrderBy(p => p.Dob);