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

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
};

Related

.Net Core 3.1 Entity Framework Slow Query Problem

There was slowness in my .net core webapi application, I reviewed and redesigned my queries to resolve this issue. The code snippet below was written to bring in sales, payments for sales, and sales territories.
I first include the condition query and then the sub-entities in the query. Then I choose which columns to work with ".Select()".
Then I want to combine this table with the name information in other tables. For example, information such as Customer Name, Product Name is in the other table.
The first block of code I share below is a slow running linq query.
result.Results =
(from s in context.Sales
join sa in context.SaleProductServiceAreas on s.SaleId equals sa.SaleId
join sp in context.SalePayments on s.SaleId equals sp.SaleId into spleft
from sp in spleft.DefaultIfEmpty()
join c in context.Customers on s.CustomerId equals c.CustomerId
join p in context.ProductServices on s.ProductServiceId equals p.ProductServiceId
where s.Date >= firstDayOfMonth && s.Date <= lastDayOfMonth
group s by
new
{
s.SaleId,
s.CustomerId,
CustomerNameSurname = c.Name + ' ' + c.Surname,
ProductServiceName = p.Name,
s.Date,
s.Total,
s.Session,
p.ProductServiceId
} into grp
select new SaleJoinDto()
{
SaleId = grp.Key.SaleId,
CustomerNameSurname = grp.Key.CustomerNameSurname,
ProductServiceName = grp.Key.ProductServiceName,
Total = grp.Key.Total,
Date = grp.Key.Date,
Session = grp.Key.Session,
CustomerId = grp.Key.CustomerId,
ProductServiceId = grp.Key.ProductServiceId,
SaleProductServiceAreas = (from sps in context.SaleProductServiceAreas
join spa in context.ProductServiceAreas on sps.ProductServiceAreaId equals spa.ProductServiceAreaId
where sps.SaleId == grp.Key.SaleId
select new SaleProductServiceAreaJoinDto()
{
SaleProductServiceAreaId = sps.SaleProductServiceAreaId,
ProductServiceAreaName = spa.Name,
ProductServiceAreaId = sps.ProductServiceAreaId,
SaleId = sps.SaleId
}).ToList(),
SalePayments = (from spp in context.SalePayments
where spp.SaleId == grp.Key.SaleId
select new SalePaymentDto()
{
SaleId = spp.SaleId,
SalePaymentId = spp.SalePaymentId,
Total = spp.Total,
PaymentMethod = spp.PaymentMethod,
Date = spp.Date
}).ToList()
}).ToList();
["NEW"] This query I wrote is the query I rewrite as a result of the articles I have shared below.
Document of Microsoft Link for query
using (var context = new AppDbContext())
{
var result = new PagedResult<SaleJoinDto>();
result.CurrentPage = pageNumber;
result.PageSize = pageSize;
var pageCount = (double)result.RowCount / pageSize;
result.PageCount = (int)Math.Ceiling(pageCount);
var skip = (pageNumber - 1) * pageSize;
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
result.Results = await context.Sales
.Where(x => x.Date >= firstDayOfMonth && x.Date <= lastDayOfMonth)
.Include(x => x.SalePayments)
.Include(x => x.SaleProductServiceAreas)
.Select(s => new Sale()
{
SaleId = s.SaleId,
CustomerId = s.CustomerId,
Date = s.Date,
Total = s.Total,
Session = s.Session,
SalePayments = s.SalePayments,
SaleProductServiceAreas = s.SaleProductServiceAreas
})
.Join(context.Customers, sales => sales.CustomerId, customers => customers.CustomerId, (sales, customers) => new
{
sales,
customers
})
.Join(context.ProductServices, combinedSaleAndCus => combinedSaleAndCus.sales.ProductServiceId, product => product.ProductServiceId, (combinedSaleAndCus, product) => new SaleJoinDto()
{
SaleId = combinedSaleAndCus.sales.SaleId,
CustomerId = combinedSaleAndCus.sales.CustomerId,
Date = combinedSaleAndCus.sales.Date,
Total = combinedSaleAndCus.sales.Total,
Session = combinedSaleAndCus.sales.Session,
CustomerNameSurname = combinedSaleAndCus.customers.Name,
SalePayments = combinedSaleAndCus.sales.SalePayments.Select(x => new SalePaymentDto()
{
Date = x.Date,
PaymentMethod = x.PaymentMethod,
SaleId = x.SaleId,
SalePaymentId = x.SalePaymentId,
Total = x.Total
}).ToList(),
SaleProductServiceAreas = combinedSaleAndCus.sales.SaleProductServiceAreas.Join(context.ProductServiceAreas, sp => sp.ProductServiceAreaId, psa => psa.ProductServiceAreaId, (sp, psa) => new SaleProductServiceAreaJoinDto()
{
SaleProductServiceAreaId = sp.SaleProductServiceAreaId,
ProductServiceAreaName = psa.Name
}).ToList()
})
.ToListAsync();
result.RowCount = result.Results.Count();
result.Results = result.Results.OrderByDescending(x => x.Date).Skip(skip).Take(pageSize).ToList();
return result;
}
The problem is I do get the following error when I rewrite it according to this new query.
Where am I making a mistake in the query I just wrote?
{"The LINQ expression 'DbSet\r\n .Where(s => s.Date >=
__firstDayOfMonth_0 && s.Date <= __lastDayOfMonth_1)\r\n .Join(\r\n outer: DbSet, \r\n inner: s => s.CustomerId, \r\n
outerKeySelector: c => c.CustomerId, \r\n innerKeySelector: (s,
c) => new TransparentIdentifier<Sale, Customer>(\r\n Outer
= s, \r\n Inner = c\r\n ))\r\n .Join(\r\n outer: DbSet, \r\n inner: ti => new Sale{ \r\n
SaleId = ti.Outer.SaleId, \r\n CustomerId =
ti.Outer.CustomerId, \r\n Date = ti.Outer.Date, \r\n
Total = ti.Outer.Total, \r\n Session = ti.Outer.Session,
\r\n SalePayments = (MaterializeCollectionNavigation(\r\n
navigation: Navigation: Sale.SalePayments,\r\n
subquery: DbSet\r\n .Where(s0 =>
EF.Property(ti.Outer, "SaleId") != null &&
EF.Property(ti.Outer, "SaleId") == EF.Property(s0,
"SaleId"))), \r\n SaleProductServiceAreas =
(MaterializeCollectionNavigation(\r\n navigation:
Navigation: Sale.SaleProductServiceAreas,\r\n subquery:
DbSet\r\n .Where(s1 =>
EF.Property(ti.Outer, "SaleId") != null &&
EF.Property(ti.Outer, "SaleId") == EF.Property(s1,
"SaleId"))) \r\n }\r\n .ProductServiceId, \r\n
outerKeySelector: p => p.ProductServiceId, \r\n
innerKeySelector: (ti, p) => new
TransparentIdentifier<TransparentIdentifier<Sale, Customer>,
ProductService>(\r\n Outer = ti, \r\n Inner =
p\r\n ))'
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 either AsEnumerable(),
AsAsyncEnumerable(), ToList(), or ToListAsync(). See
https://go.microsoft.com/fwlink/?linkid=2101038 for more
information."}
Removed not needed joins and grouping. It should be faster.
var query =
from s in context.Sales
join c in context.Customers on s.CustomerId equals c.CustomerId
join p in context.ProductServices on s.ProductServiceId equals p.ProductServiceId
where s.Date >= firstDayOfMonth && s.Date <= lastDayOfMonth
select new SaleJoinDto()
{
SaleId = s.SaleId,
CustomerNameSurname = c.Name + ' ' + c.Surname,
ProductServiceName = p.ProductServiceName,
Total = s.Total,
Date = s.Date,
Session = s.Session,
CustomerId = s.CustomerId,
ProductServiceId = p.ProductServiceId,
SaleProductServiceAreas = (from sps in context.SaleProductServiceAreas
join spa in context.ProductServiceAreas on sps.ProductServiceAreaId equals spa.ProductServiceAreaId
where sps.SaleId == s.SaleId
select new SaleProductServiceAreaJoinDto()
{
SaleProductServiceAreaId = sps.SaleProductServiceAreaId,
ProductServiceAreaName = spa.Name,
ProductServiceAreaId = sps.ProductServiceAreaId,
SaleId = sps.SaleId
}).ToList(),
SalePayments = (from spp in context.SalePayments
where spp.SaleId == s.SaleId
select new SalePaymentDto()
{
SaleId = spp.SaleId,
SalePaymentId = spp.SalePaymentId,
Total = spp.Total,
PaymentMethod = spp.PaymentMethod,
Date = spp.Date
}).ToList()
};
result.Results = query.ToList();
Anyway, even joins can be simplified if you have navigation properties which are not shown in original question.
I fixed the slow responsiveness of the app.
I was running the application on windows host. I changed my hosting to Centos 7 which is a linux distribution. Then when I run the application on Centos 7, the application accelerated perfectly and took flight.
My advice to all .net Core app developers, migrate your apps to linux. It is built to run on .net core linux distributions.
I share the problems I encountered while migrating the application to linux and how I solved it in the link below.
.Net Core 3.1 deploy on Centos 7

Convert SQL Server query to Entity Framework query

I have a SQL Server query like this:
select
month(fact_date) as month,
sum(case when beef_dairy_stat = 1 and param_id = 1 then 1 else 0 end) as cnt
from
user_behave_fact
where
YEAR(fact_date) = 2018
group by
month(fact_date)
order by
month
with a result of
month cnt
------------
1 10
2 20
Now I need to convert this query to its corresponding Entity Framework query.
This is my current attempt:
var sql_rez_ICC = new List<Tuple<int, int>>();
sql_rez_ICC = db.user_behave_fact
.Where(x => x.fact_date.Value.Year == selected_year)
.GroupBy(y => y.fact_date.Value.Month)
.Select(y =>new { month = y.Select(x=>x.fact_date.Value.Month), icc_count = y.Count(x => x.beef_dairy_stat == true && x.param_id == 1) })
.AsEnumerable()
.Select(y => new Tuple<int, int>(y.month, y.icc_count))
.ToList();
However on second .Select, I get an error on month which is
Cannot convert from System.Collection.Generic.IEnumrable to int
y.Select(x=>x.fact_date.Value.Month) returns an IEnumerable<int>. Use y.Key instead.

How to convert T-SQL into LINQ

I have following code in a T-SQL query and I need to convert (rewrite) it into LINQ. Can somebody help me? Thanks
SELECT (select max(X.PocetDniPoPlatnosti)
from
(
select
(select top 1 datediff(day,datumplatnosti,getdate()) from planrealizace p
where p.cinnostsopidsop = cinnostsop.idsop and datumplatnosti <= getdate() and p.provest = 1 and p.datumprovedeni is null
order by p.datumplatnosti desc) as PocetDniPoPlatnosti
from cinnostsop
where cinnostSOP.LegislativneVyznamna = 1 and (CinnostSOP.ObjektId = 131476)) X) as PoPlatnosti
this should work, but I could not try it as I do not have any programming tools at home, so feel free to let me know if this doesn't work, and we can improve it together
var max = (from cp in cinnostsop.Where(c => c.LegislativneVyznamna = 1 && c.ObjektId = 131476)
join p in (
planrealizace.
Where(pz => pz.datumplatnosti <= DateTime.Now &&
pz.provest = 1 and pz.datumprovedeni is null).
GroupBy(pz => pz.cinnostsopidsop, pz => pz).
Select(g =>
new {
id = g.Key,
firstdate = (g.OrderByDescending(
pz => pz.datumplatnosti).
First().datumplatnosti - DateTime.Now
).Totaldays
})
) on cp.idsop equals p.id
select p.firstdate).Max(d => d);

I need help re-writing a SQL query into LINQ format

I'm not good with LINQ yet and could use some help with the syntax.
Thanks!
The below query needs to be written in LINQ for C#.
SELECT Galleries.GalleryTitle, Media.*
FROM Galleries
INNER JOIN Media ON Galleries.GalleryID = Media.GalleryID
WHERE (Galleries.GalleryID = 150)
ORDER BY MediaDate DESC, MediaID DESC
Or with query syntax:
var query = from g in db.Galleries
join m in db.Media on g.GalleryID equals m.GalleryID
where g.GalleryID == 150
orderby m.MediaDate descending, m.MediaID descending
select new { g.GalleryTitle, Media = m };
Something like this:
var query = db.Galleries
.Join(db.Media, g => g.GalleryID, m => m.GalleryID, (g, m) => new {g, m})
.Where(r.g.GalleryID == 150)
.Select(res => new {res.g.GalleryTitle, Media = res.m}
.OrderByDescending(o => o.Media.MediaDate)
.ThenByDescending(o => o.Media.MediaID);

How do I translate this GROUP BY / MIN SQL query into LINQ?

I plan on using this in a subquery but can't figure out the correct syntax to translate the following query into LINQ:
select ChapterID, min(MeetingDate)
from ChapterMeeting
group by ChapterID
var query = myDataContext.ChapterMeeting
.GroupBy(cm => cm.ChapterID)
.Select(g => new {
g.Key,
MinMeetingDate = g.Min(cm => cm.MeetingDate)
});
Well, Amy beat me to it, but in case you wanted to see it with the "comprehension" syntax:
var q = (
from cm in context.ChapterMeeting
group cm by cm.ChapterID into cmg
select new {
ChapterID = cmg.Key,
FirstMeetingDate = cmg.Min(cm => cm.MeetingDate)});