LINQ to Entities does not recognize ToString using query syntax - c#

I'm getting this error in a LINQ query (query syntax used). In the past I've gotten this error when using dot syntax in my LINQ query so all I had to do is a call to ToList() and then select using an anonymous class. But in my case where I'm now using query syntax, how do I do the same thing? Yes I'm using EF.
Here is the code:
var dataList = from h in context.Horaires
join e in context.Employes on h.iIdEmploye equals e.iIdEmploye
join p in context.Postes on h.iIdPoste equals p.iIdPoste
join g in context.GroupesPostes on p.iIdGroupePoste equals g.iIdGroupePoste
join en in context.EnsemblesPostes on g.iIdEnsemblePoste equals en.iIdEnsemblePoste
join d in context.Departements on e.iIdDepartement equals d.iIdDepartement
where p.bitActif == true && h.dteDate == p.dteDate
orderby e.sIdEmployeClient
select new ScenarioScheduleItemModel
{
H = "D",
EmployeeSchedule = "EmployeeSchedule",
EmployeeSchedule2 = "EmployeeSchedule",
EmployeeXrefCode = e.sIdEmployeClient,
// ToString used here for StartTime and EndTime
StartTime = h.dteDate.ToString(CultureInfo.InvariantCulture).Substring(0, 10) + "T" + p.dteHeureDebut.ToString(CultureInfo.InvariantCulture).Substring(11, 8),
EndTime = h.dteDate.ToString(CultureInfo.InvariantCulture).Substring(0, 10) + "T" + p.dteHeureFin.ToString(CultureInfo.InvariantCulture).Substring(11, 8),
DeptXrefCode = d.sNom,
JobXrefCode = p.sNom,
OrgUnit = string.Empty,
XrefCode = string.Empty,
OrgLocationTypeXrefCode = string.Empty,
PayAdjCodeXrefCode = string.Empty
};
var result = dataList.Distinct().ToList();

You could just select the "raw" values then use AsEnumerable and a Select to get the desired values
var dataList = (from h in context.Horaires
...
select new { e, h, p, d }).AsEnumerable()
.Select(anon => new ScenarioScheduleItemModel
{
...
StartTime = anon.h.dteDate.ToString(CultureInfo.InvariantCulture)
.Substring(0, 10)
+ "T" + anon.p.dteHeureDebut.ToString(CultureInfo.InvariantCulture)
.Substring(11, 8),
EndTime = anon.h.dteDate.ToString(CultureInfo.InvariantCulture)
.Substring(0, 10)
+ "T" + anon.p.dteHeureFin.ToString(CultureInfo.InvariantCulture)
.Substring(11, 8),
...
});

It may make more sense to use something like string.Format
StartTime = string.Format("{0:MM/dd/yyyy}T{1:hh:mm:ss}", h.dteDate, p.dteHeureDebut),
EndTime = string.Format("{0:MM/dd/yyyy}T{1:hh:mm:ss}", h.dteDate, p.dteHeureFin),

Just for your info. here's a generic form what you need to do:
var dbQuery = from x in db.Table
// do stuff with x what will be translated to SQL
select x;
var memoryQuery = from z in dbQuery.AsEnumerable() // <-- !
// do stuff with z in memory
select z;

Related

Converted sql query to linq but not getting any result

As I am new to Linq and Entity Framework.
The following is my working stored procedure which includes a value that is a comma separated string (the SUBSTRING clause)
SELECT DISTINCT
SR.StudentRequestId,
SR.RegistrationId,
SR.Location,
SR.PaymentMethod,
SR.CreatedOn,
C.ClassName,
CC.CampusName,
CASE WHEN ISNULL(TSR.StatusId,0)=0 THEN 1 ELSE TSR.StatusId END AS StatusId,
SUBSTRING(
(SELECT', ' + REPLACE(REPLACE(ST1.FromTime,'AM',''),'PM','') + '-'+ ST1.ToTime AS [text()]
FROM dbo.StudentRequestTimings ST1
WHERE ST1.StudentRequestId = SRT.StudentRequestId
ORDER BY ST1.CreatedOn FOR XML PATH ('')
), 2, 1000) [Time] FROM StudentRequest SR
INNER JOIN Registration R ON R.RegistrationId = SR.RegistrationId
INNER JOIN Campus CC ON CC.CampusId = R.CampusId
INNER JOIN Class C ON C.ClassId = SR.ClassId
LEFT JOIN TutorClasses TC ON SR.ClassId = TC.ClassId
LEFT JOIN StudentRequestTimings SRT ON SR.StudentRequestId = SRT.StudentRequestId
LEFT JOIN TutorStudentRequest TSR ON TSR.StudentRequestId = SRT.StudentRequestId AND TutorId = #RegistrationId
WHERE TC.RegistrationId = #RegistrationId
ORDER BY SR.CreatedOn DESC
I have a requirement to use this data in a PagedList method that accepts a IQueryable<T> and I want to convert this SP to a LINQ query that returns a IQueryable (internally the PagedList method uses .Skip() and .Take() to perform server side paging).
The following is my attempt so far, but I do not know why i am not getting to get the expected result as getting from SQL query. I think some thing is wrong in my below code. Can any one identify what is wrong in below code?
var model = (from sr in db.StudentRequests
join r in db.Registrations on sr.RegistrationId equals r.RegistrationId
join cc in db.Campus on r.CampusId equals cc.CampusId
join c in db.Classes on sr.ClassId equals c.ClassId
from tc in db.TutorClasses.Where(t => t.ClassId == sr.ClassId).DefaultIfEmpty()
from srt in db.StudentRequestTimings.Where(s => s.StudentRequestId == sr.StudentRequestId).DefaultIfEmpty()
from tsr in db.TutorStudentRequests.Where(t => t.StudentRequestId == srt.StudentRequestId && t.TutorId == registrationid).DefaultIfEmpty()
where tc.RegistrationId == registrationid
select new TutorDashboard
{
StudentRequestId = sr.StudentRequestId,
RegistrationId = sr.RegistrationId,
Location = sr.Location,
PaymentMethod = sr.PaymentMethod,
CreatedOn = sr.CreatedOn,
ClassName = c.ClassName,
CampusName = cc.CampusName,
Time = string.Join(",", db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId).Select(p => p.FromTime.ToString().Replace("AM", "").Replace("PM", "") + "-" + p.ToTime.ToString())),
}).Distinct();
Can any one help me out for why I am not getting proper result from above linq query?
Issue is that on adding below code to Linq I am facing issue, How can I resolve this
Time = string.Join(",", db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId).Select(p => p.FromTime.ToString().Replace("AM", "").Replace("PM", "") + "-" + p.ToTime.ToString())),
I had added this code because I want to get a single string from multiple row
1:00-1:30 PM, 2:00=2:30 PM
5:00-5:30 PM
Like wise
As there was an issue in converting comma seperated code I had implement below code
var query = (from sr in db.StudentRequests
join r in db.Registrations on sr.RegistrationId equals r.RegistrationId
join cc in db.Campus on r.CampusId equals cc.CampusId
join c in db.Classes on sr.ClassId equals c.ClassId
from tc in db.TutorClasses.Where(t => t.ClassId == sr.ClassId).DefaultIfEmpty()
from srt in db.StudentRequestTimings.Where(s => s.StudentRequestId == sr.StudentRequestId).DefaultIfEmpty()
from tsr in db.TutorStudentRequests.Where(t => t.StudentRequestId == srt.StudentRequestId && t.TutorId == registrationid).DefaultIfEmpty()
where tc.RegistrationId == registrationid
select new
{
StudentRequestId = sr.StudentRequestId,
RegistrationId = sr.RegistrationId,
Location = sr.Location,
PaymentMethod = sr.PaymentMethod,
CreatedOn = sr.CreatedOn,
ClassName = c.ClassName,
CampusName = cc.CampusName,
StatusId = tsr.StatusId == null ? 1 : tsr.StatusId,
Time = db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId).Select(p => p.FromTime.ToString().Replace("AM", "").Replace("PM", "") + "-" + p.ToTime)
}).ToList().GroupBy(p => new { p.StudentRequestId }).Select(g => g.First()).ToList();
var model = query.AsEnumerable().Select(x => new TutorDashboard
{
StudentRequestId = x.StudentRequestId,
RegistrationId = x.RegistrationId,
Location = x.Location,
PaymentMethod = x.PaymentMethod,
CreatedOn = x.CreatedOn,
ClassName = x.ClassName,
CampusName = x.CampusName,
StatusId = x.StatusId == null ? 1 : x.StatusId,
Time = string.Join(",", x.Time),
}).ToList().ToPagedList(page ?? 1, 1);
May this code will be helpful to some who need comma separated value with multiple left join

Sum Columns from joined tables to get a calculated value using Linq to SQL

In the above diagram for each customer I want to select all orders and then for each order I have calculate a TotalPrice = (Sum of all Food Items included in order * Quantity) + ExtraPrice. I am struggling to create a query for it using linq to sql.
var res = (from a in dc.orders
join b in dc.orderLines on a.orderId equals b.fk_orderId
join c in dc.foodItems on b.fk_foodId equals c.foodId
where a.fk_custId == cID
group new { a,c,b } by a into g
select new
{
OID1 = g.Key.orderId,
date1 = g.Key.date.Value.Date,
price1 = g.Sum(x => x.c.price * x.b.quantity) + g.Key.orderLines.Select(o => o.extraPrice).Sum()
});
Given above is linq query I was looking for.
Should be something close to this. I'm not around a computer to test so let me know if you get errors.
db.orders.Select(o => new { o.orderid, o.date, TotalPrice = ( (o.orderLines.Select(ol => ol.food items.Count()).Sum() * o.Quantity) + o.extraPrice) } )

Linq between dates

So i have a query that is getting data correctly but as soon as I try to filter out the linq statement with a where between dates, I consistently get zero results.
var query= Enumerable.Empty<CustomClass>().AsQueryable();
query= (from auto in db.AutoInvs
join deal in db.Deals on new { inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT} equals new {inv = deal.INVUID,client = deal.CLIENTID, acct = (int?) deal.ACCOUNT}
join dmCust in db.DMCusts on new {inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT.ToString()} equals new {inv = dmCust.INVUID, client = dmCust.CLIENTID, acct = dmCust.ACCOUNT}
join act in db.Acts on new { inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT.ToString()} equals new { inv = act.INVUID, client = act.CLIENTID, acct = act.Key }
where auto.DATAPROCESSEDDATE == null && auto.INVUID != ""
select new CustomClass()
{
AutoInv = auto,
Deal = deal,
DmCust = dmCust,
Act = act
});
var filteredData = query.Where(c => c.AutoInv.DATESOLD >= dateFrom.Value && c.AutoInv.DATESOLD <= dateTo.Value).AsQueryable();
Console.WriteLine(filteredData.ToList().Count);
Using this stripped down version (and my own data), it works for me:
var query = Enumerable.Empty<Tbl1>().AsQueryable();
DateTime? dateFrom = new DateTime(2017, 5, 10);
DateTime? dateTo = new DateTime(2017, 5, 20);
query = (from auto in db.Tbl1s
select auto);
var filteredData = query.Where(c => c.StartDate >= dateFrom.Value
&& c.StartDate <= dateTo.Value).AsQueryable();
filteredData.Dump();
One possible problem you may be having is that dateTo would be the exclusive end point --- Unless DATESOLD is exactly midnight, you won't get any that are on the end date.

SQL to LINQ C# EntityFramework

I'm on my way to convert all my straight SQL programms to Entity Framework.
So I need LINQ and LE.
But I'm not able to do this in LINQ:
SELECT
a.abteilung,
sum(d.kosten)
FROM
tdaten d,
abteilung a
WHERE
d.sourcenr = a.sourcenr AND
d.datum between '" + string.Format("{0:yyyy-MM-dd}", DTP_from.Value) + "'
and '"+string.Format(format: "{0:yyyy-MM-dd}", arg0: DTP_to.Value)+"'
GROUP BY
a.abteilung;", _con);
Thanks
Something like this?
from a in abteilung
join d in tdaten
on a.sourcenr equals d.sourcenr
where d.datum >= DTP_from.Value && d.datum <= DTP_to.Value
group d by a.abteilung into g
select new
{
abteilung = g.Key,
kosten = g.Sum(d => d.kosten)
}
An option.
The whole can b breakdown into 3 sub-queries in LINQ.
Get the Records
Take the sum
The group by the result.
Following are the queries.:
var results = from a in abteilung
join d in tdated on d.sourcenr equals a.sourcenr
where
d.dateum >= fromDate && d.datum <= ToDate.AddDays(1)
select new {a.abteilung, d.kosten};
var sumOfKotsen = results.Sum(x=>x.kosten);
var groupResult = results.GroupBy(x=>x.abteilung);
Assuming that the dateFrom and ToDate are the DateTime objects.

This LINQ-to-Entities join seems overly complex, am I doing something wrong?

I have two queries that I need to combine in LINQ that both actually come from the same table. The reason for this is that one of the queries needs to get the max of a field for each day and then sum the days together where the second query can just sum everything right off the bat. Here is the first query:
var queryDownload = from p in
(from p in almdbContext.cl_contact_event
where p.time_of_contact >= startDate && p.time_of_contact < endDate && p.input_file_name.Contains(inputFileName) && listName.Contains(listName)
group p by new
{
date = EntityFunctions.CreateDateTime(p.time_of_contact.Value.Year, p.time_of_contact.Value.Month, p.time_of_contact.Value.Day, 0, 0, 0),
listName = p.contact_list_name
} into g
select new
{
date = g.Key.date,
listName = g.Key.listName,
download = g.Max(a => a.total_number_of_records)
})
group p by p.listName into g
select new
{
listName = g.Key,
totalDownload = g.Sum(a => a.download),
};
This is the second:
var queryPenData = from p in almdbContext.cl_contact_event
where p.time_of_contact >= startDate && p.time_of_contact < endDate && p.input_file_name.Contains(inputFileName) && listName.Contains(listName)
group p by p.contact_list_name into g
select new
{
listName = g.Key,
dials = g.Sum(a => a.ov_dial_start_time != null ? 1 : 0),
agentConnects = g.Sum(a => a.agent_login_name != null ? 1 : 0),
abandons = g.Sum(a => a.response_status == "DAC" || a.response_status == "DAD" ? 1 : 0),
rightPartyContacts = g.Sum(a => a.response_status == "PTP" || a.response_status == "RPC" ? 1 : 0),
promiseToPays = g.Sum(a => a.response_status == "PTP" ? 1 : 0),
talkTime = g.Sum(a => EntityFunctions.DiffSeconds(a.ov_call_connected_time, a.ov_trunk_released_time)) ?? 0,
wrapTime = g.Sum(a => EntityFunctions.DiffSeconds(a.ov_trunk_released_time, a.record_released_time)) ?? 0
};
And this is the query joining them together.
var queryJoin = from qd in queryDownload
join qp in queryPenData
on qd.listName equals qp.listName
select new
{
listName = qp.listName,
download = qd.totalDownload,
dials = qp.dials,
agentConnects = qp.agentConnects,
abandons = qp.abandons,
rightPartyContacts = qp.rightPartyContacts,
promiseToPays = qp.promiseToPays,
talkTime = qp.talkTime,
wrapTime = qp.wrapTime
};
This seems extremely verbose/roundabout to me. Is there a better way I can write/approach this to shrink/simplify the code?
For your last query could you not just do something like this?
var queryJoin = from qd in queryDownload join qpd in queryPenData on qd.listname equals qpd....
Should be able to do this:
var queryJoin = from qd in queryDownload
join qp in queryPenData
on qd.listName equals qp.listName
select new
{
qp, qd
};
From what I can tell you've already formed your data in queryPenData so there is no reason to re-assign it to new variables in the final join. Just select the object which will allow you to traverse into the anonymous type in queryPenData. I think...

Categories