LInq to Entity select new COUNT where - c#

I've created the most complex linq query ever, but still do not have exactly what I need. From this query, I need to know how many related students in the EventStudents table that have a DateDeleted == null. So, the StudentCount = ev.EventStudents - where DateDeleted == null .Count().
Can anyone help with this please?
var inf = (from ev in db.Events
where (ev.StartDate >= beginDate && ev.StartDate <= endDate)
&& ev.DeletedDate == null
orderby ev.StartDate descending
select new
{
EventID = ev.EventID,
EventTitle = ev.Title,
EventDate = ev.StartDate,
StudentCount = ev.EventStudents.Count(),
CreatedUsername = ev.CreatedUsername
}).AsEnumerable().Select(x => new
{
EventID = x.EventID,
EventTitle = x.EventTitle,
EventDate = x.EventDate,
StudentCount = x.StudentCount,
CreatedUsername = x.CreatedUsername,
CreatedFullname = sortedUserDictionary.Where(u => u.Value == x.CreatedUsername)
.Select(f => f.Key)
.FirstOrDefault() ?? x.CreatedUsername
});

Change ev.EventStudents.Count() to ev.EventStudents.Count(es => es.DateDeleted == null).

Related

C# subquery in LINQ select

I'm trying to convert this query to LINQ, but I'm not getting the value of the subquery
QUERY:
select c.cod, c.cpfcnpj, c.razaosocial, c.nome, c.fone, c.celular, c.email, c.dtcad, s.dataval as validade,
(select max(datapagamento) from vendas where c.cod = coduser) as datapag
from usuarios c, libsys s
WHERE c.cod = s.codcli
and c.cod in (select coduser from vendas)
AND c.cod in (select l.codcli from libsys l where l.dataval >= current_date)
order by c.dtcad asc
LINQ:
var rel = await (from u in _contexto.usuarios
from v in _contexto.libsys
where (
(u.cod == v.codcli) &&
_contexto.vendas.Any(y => y.coduser == u.cod) &&
_contexto.libsys.Any(y => y.codcli == u.cod && y.pcpdataval >= System.DateTime.Now)
)
select new RelatorioLicsModel
{
cod = u.cod,
cpfcnpj = u.cpfcnpj,
razaosocial = u.razaosocial,
nome = u.nome,
fone = u.fone,
celular = u.celular,
email = u.email,
dtcad = u.dtcad,
validade = v.pcpdataval.ToString(),
dtpag = Convert.ToDateTime(_contexto.vendas.Where(s => s.datapagamento == _contexto.vendas.Max(x => x.datapagamento) && s.coduser == u.cod).FirstOrDefault())
}).ToListAsync();
the error I get is:
{"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(PARTITION BY v.coduser ORDER BY v.cod) AS row\r\n FROM vendas ' at line 7"}
is this the correct way to do this? thanks for any help!
Problem with dtpag property.
var query =
from u in _contexto.usuarios
from v in _contexto.libsys
where (
(u.cod == v.codcli) &&
_contexto.vendas.Any(y => y.coduser == u.cod) &&
_contexto.libsys.Any(y => y.codcli == u.cod && y.pcpdataval >= System.DateTime.Now)
)
select new RelatorioLicsModel
{
cod = u.cod,
cpfcnpj = u.cpfcnpj,
razaosocial = u.razaosocial,
nome = u.nome,
fone = u.fone,
celular = u.celular,
email = u.email,
dtcad = u.dtcad,
validade = v.pcpdataval.ToString(),
dtpag = Convert.ToDateTime(_contexto.vendas.Where(s => s.coduser == u.cod).Max(x => x.datapagamento))
}

EF Core - Join on 2 IQueryable that one of them has group by not translated to SQL

I want to join two tables with EF Core with this code:
var fromDate = model.FromDate;
var toDate = model.ToDate;
var tourDate = _eContext.TourDates.OrderBy(x => x.Date).Where(x =>
(fromDate == null || x.Date >= fromDate) && (toDate == null || x.Date <= toDate))
.GroupBy(x => x.TourId).Select(g => new { TourId = g.Key, TourDateID = g.Min(y => y.TourDateId) });
var tours1 = _eContext.TourDetails;
var joinres = tours1.Join(tourDate
, tu => tu.TourDateId, td => td.TourDateId, (tu, td) => new { TourId = tu.TourId, TourDetailId = tu.Id, TourDateId = td.TourDateID });
var TourList = joinres.ToList();
When I execute the .ToList() method, I get this warning:
The LINQ expression 'join TourDate td in
value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[ModelLayer.EuropaMundo.TourDate])
on [td].TourDateID equals [td].TourDateId' could not be translated and
will be evaluated locally.
Is there any way to translate LINQ to SQL?

Why Same where clause need to write multiple times in a Linq Query for following SQL

What will be the proper linq syntax of below SQL Query ?
select a.id, a.AppointmentStatusID, ad.ID as DetailID
from [dbo].[Appointment] a, [dbo].[AppointmentDetail] ad
where a.[ID] = ad.[AppointmentID]
and a.CompanyID = 'a3dea87a-804e-4115-98cf-472988cf1678'
and a.LocationID = '3165caca-2a48-46f0-bbed-578cff29167t'
and ad.AppDateFrom <= {ts '2017-11-14 23:59:31'}
and ad.AppDateTo >= {ts '2017-11-14 00:00:00'}
and ad.[ApprovalStatusID] = 2
Problem I faced:
I required to filter Where Condition two times 1st at the time within the join & 2nd time during the object.Select expression, please check bellow
var results = (from a in appointments
join ad in _appointmentDetailRepository.GetAll() on a.ID equals ad.AppointmentID
where ad.ApprovalStatusID == 2
&& DbFunctions.TruncateTime(ad.AppDateFrom) <= DbFunctions.TruncateTime(viewmodel.AppointmentDate)
&& DbFunctions.TruncateTime(ad.AppDateTo) >= DbFunctions.TruncateTime(viewmodel.AppointmentDate)
orderby a.ID
select new Appointment
{
ID = a.ID,
CompanyID = a.CompanyID,
LocationID = a.LocationID,
AppointmentDetail = a.AppointmentDetail.Select(ad => new AppointmentDetail
{
ID = ad.ID,
AppDateFrom = ad.AppDateFrom,
AppDateTo = ad.AppDateTo,
AppointmentStatusID = ad.AppointmentStatusID,
}).Where(ad=> ad.ApprovalStatusID == 2
&& DbFunctions.TruncateTime(ad.AppDateFrom) <= DbFunctions.TruncateTime(viewmodel.AppointmentDate)
&& DbFunctions.TruncateTime(ad.AppDateTo) >= DbFunctions.TruncateTime(viewmodel.AppointmentDate)).ToList()
}).GroupBy(x => x.ID).Select(x => x.DefaultIfEmpty().FirstOrDefault());
Query : Why I required to write Where clause 2 times ?
Required Result
An Appointment Object --> Containing ICollection<AppoinmentDetails> if Details.Where Condition == True
From what I see (without knowing the model you have), it looks like you should use the already joined and filtered Details from ad instead of looking it up again from the Property a.AppointmentDetail...
Untested:
select new Appointment
{
ID = a.ID,
CompanyID = a.CompanyID,
LocationID = a.LocationID,
AppointmentDetail = ad.ToList(), // <-- don't you think?
...
}
For the given SQL query
select a.id, a.AppointmentStatusID, ad.ID as DetailID
from [dbo].[Appointment] a, [dbo].[AppointmentDetail] ad
where a.[ID] = ad.[AppointmentID]
and a.CompanyID = 'a3dea87a-804e-4115-98cf-472988cf1678'
and a.LocationID = '3165caca-2a48-46f0-bbed-578cff29167t'
and ad.AppDateFrom <= {ts '2017-11-14 23:59:31'}
and ad.AppDateTo >= {ts '2017-11-14 00:00:00'}
and ad.[ApprovalStatusID] = 2
LINQ query can be written as
var results = (from a in appointments
join ad in appointmentDetails on a.ID equals ad.AppointmentID
where ad.ApprovalStatusID == 2
&& a.CompanyID == "a3dea87a-804e-4115-98cf-472988cf1678"
&& a.LocationID == "3165caca-2a48-46f0-bbed-578cff29167t"
&& ad.AppDateFrom.Date <= viewmodel.AppointmentDate.Date
&& ad.AppDateTo.Date >= viewmodel.AppointmentDate.Date
select new
{
ID = a.ID,
AppointmentStatusID = a.AppointmentStatusID,
DetailID = ad.ID
}).ToList();
You can also write it like
var results = appointmentDetails
.Where(ad => ad.AppDateFrom.Date <= viewmodel.AppointmentDate.Date
&& ad.AppDateTo.Date >= viewmodel.AppointmentDate.Date
&& ad.ApprovalStatusID == 2
&& ad.Appointment.CompanyID == "a3dea87a-804e-4115-98cf-472988cf1678"
&& ad.Appointment.LocationID == "3165caca-2a48-46f0-bbed-578cff29167t")
.Select(ad =>
new
{
ID = ad.Appointment.ID,
AppointmentStatusID = ad.Appointment.AppointmentStatusID,
DetailID = ad.ID
})
.ToList()
As per the updated question, to get the the Appointment object with a collection of AppointmentDetails, please try this query
var results = appointmentDetails
.Where(ad => ad.AppDateFrom.Date <= viewmodel.AppointmentDate.Date
&& ad.AppDateTo.Date >= viewmodel.AppointmentDate.Date
&& ad.ApprovalStatusID == 2
&& ad.Appointment.CompanyID == "a3dea87a-804e-4115-98cf-472988cf1678"
&& ad.Appointment.LocationID == "3165caca-2a48-46f0-bbed-578cff29167t")
.Select(ad =>
new
{
ID = ad.Appointment.ID,
AppointmentStatusID = ad.Appointment.AppointmentStatusID,
Detail = ad
})
.AsEnumerable()
.GroupBy(a => new { a.ID, a.AppointmentStatusID })
.Select(a => new Appointment
{
ID = a.Key.ID,
AppointmentStatusID = a.Key.AppointmentStatusID,
AppointmentDetails = a.Select(d => d.Detail).ToList()
})
.ToList();

multiple linq orderby not working

I have multiple OrderBy but only the first order column is working
public static List<vwData> GetAllData(string startDate, string endDate)
{
DateTime dtStart = Convert.ToDateTime(startDate).Date;
DateTime dtEndDate = Convert.ToDateTime(endDate).Date;
var entities = new DataEntities();
var query = from c in entities.vwData
let eventDate = EntityFunctions.TruncateTime(c.EventCreateDate)
orderby c.EventCreateDate ascending, c.StartDateTime ascending
where eventDate >= dtStart && eventDate <= dtEndDate
select c;
return query.ToList();
}
Consider using ThenBy:
public static List<vwData> GetAllData(string startDate, string endDate)
{
DateTime dtStart = Convert.ToDateTime(startDate).Date;
DateTime dtEndDate = Convert.ToDateTime(endDate).Date;
var entities = new DataEntities();
var query = from c in entities.vwData
let eventDate = EntityFunctions.TruncateTime(c.EventCreateDate)
orderby c.EventCreateDate ascending
thenby c.StartDateTime ascending
where eventDate >= dtStart && eventDate <= dtEndDate
select c;
return query.ToList();
}
Orderby should be after condition check and default ordering is ascending
var query = from c in entities.vwData
let eventDate = EntityFunctions.TruncateTime(c.EventCreateDate)
where eventDate >= dtStart && eventDate <= dtEndDate
orderby c.EventCreateDate, c.StartDateTime
select c;
return query.ToList();
OR
Using Linq, we can do as follows
var query = entities.vwData.Where(i =>
{
var eventDate = EntityFunctions.TruncateTime(i.EventCreateDate);
if (eventDate >= dtStart && eventDate <= dtEndDate)
return true;
return false;
})
.OrderBy(j => j.EventCreateDate)
.ThenBy(k => k.StartDateTime)
.Select(m => m);
return query.ToList();
Try following query. It will help you:
var query = entities.vwData.Where(i => EntityFunctions.TruncateTime(i.OrderDate) >= dtStart && EntityFunctions.TruncateTime(i.OrderDate) <= dtEndDate )
.OrderBy(j => j.EventCreateDate)
.ThenBy(k => k.StartDateTime)
.Select(m => m);
return query.ToList();

LINQ return expression if expression does not match

I'm not sure the title explains the problem well, so here is the code. I want to return an anonymous object to bind my grid to. In that grid, I want to change usernames to fullnames, but only if I HAVE the fullname to match the username. In the query below, I get CreatedFullname IF CreatedUsername exists in userModels. If it does not exists then I don't get the record at all. What I wnat is to get the record, show UserFullname if it is available in userModels, if it is not I want to return x.CreatedUsername.
var inf = (from ev in db.Events
where (ev.StartDate >= beginDate && ev.StartDate <= endDate)
orderby ev.StartDate descending
select new
{
EventID = ev.EventID,
EventTitle = ev.Title,
EventDate = ev.StartDate,
StudentCount = ev.EventStudents.Count(),
CreatedUsername = ev.CreatedUsername
}).AsEnumerable().Select(x => new {EventID = x.EventID,
EventTitle = x.EventTitle,
EventDate = x.EventDate,
StudentCount = x.StudentCount,
CreatedUsername = x.CreatedUsername,
CreatedFullname =
userModels.Where(u => u.Username == x.CreatedUsername).FirstOrDefault().UserFullName
});
userModels is a custom object that has Username, UserFullname, Department, etc. It was collected from ActiveDirectory on pageload, based on beginDate and endDate.
You can do this:
CreatedFullname =
userModels.Where(u => u.Username == x.CreatedUsername)
.Select(x => x.UserFullName)
.FirstOrDefault() ?? x.CreatedUsername
Or this:
var inf =
(from x in
(from ev in db.Events
where (ev.StartDate >= beginDate && ev.StartDate <= endDate)
orderby ev.StartDate descending
select new
{
EventID = ev.EventID,
EventTitle = ev.Title,
EventDate = ev.StartDate,
StudentCount = ev.EventStudents.Count(),
CreatedUsername = ev.CreatedUsername
})
.AsEnumerable()
let model = userModels.FirstOrDefault(u => u.Username == x.CreatedUsername)
select new
{
EventID = x.EventID,
EventTitle = x.EventTitle,
EventDate = x.EventDate,
StudentCount = x.StudentCount,
CreatedUsername = x.CreatedUsername,
CreatedFullname = (model != null)
? x.modelUserFullName
: x.CreatedUsername
});

Categories