Group by with count on multiple table in LINQ - linq

Sql query to LINQ: Both are pasted over here, getting issue in LINQ - need suggestion:
select bm.MachineId,al.AlarmId,am.AlarmName, count(al.AlarmId)AlarmCount
from BatchMachineWise bm
join AlarmLog al on bm.MachineId = al.MachineId
join Alarm am on am.AlarmId = al.AlarmId
where bm.BatchId = 12476
group by bm.MachineId,al.AlarmId,am.AlarmName

GroupBy returns IGrouping<TKey,TElement> interface which has Key property which should be used to access fields used for grouping:
select new AlarmSummary
{
MachineId = gr.Key.MachineId,
AlarmId = gr.Key.AlarmId,
AlarmName = gr.Key.AlarmName
....
}

Related

Insert records using select in LINQ

How can we convert following query to LINQ
INSERT INTO License (PersonID, LicenseState, LicenseNumber, LicenseYear)
SELECT p.PersonID,
s.LicenseState,
s.LicenseNumber,
s.LicenseYear
FROM SourceData s
JOIN Person p
ON s.UserID = p.DomainAccountName
WHERE s.isActive = 1
var query = from s in db.SourceData
join p in db.Person on s.UserId equals p.DomainAccountName
where s.IsActive
select new License
{
PersonID = p.PersonID,
LicenseState = s.LicenseState,
LicenseNumber = s.LicenseNumber,
LicenseYear = s.LicenseYear
};
db.Licenses.AddRange(query);
That will actually give you one SQL query, and a bunch of individual SQL INSERTS. Alternately, you could use the Z.EntityFramework.Plus.EFCore nuget package, and use the code
var query = ... (same)...
db.Licenses.InsertFromQuery(query);
which should use the single SQL statement you posted.
UPDATE: I originally confused the retail/licensed Z.EntityFramework.Extensions.EFCore with the free/open-source Z.EntityFramework.Plus.EFCore package. Code above has been updated.
If you care about performance, you don't have to load anything to the client. It is how EF Core works right now, if you want to insert something - you have to feed ChangeTracker with new records.
I would suggest EF Core extension linq2db.EntityFrameworkCore which generates exactly the same query as in question but via LINQ. Note that I'm one of the creators.
Then you can do the following:
var query =
from s in db.SourceData
join p in db.Person on s.UserId equals p.DomainAccountName
where s.IsActive
select new License
{
PersonID = p.PersonID,
LicenseState = s.LicenseState,
LicenseNumber = s.LicenseNumber,
LicenseYear = s.LicenseYear
};
await query.InsertAsync(db.License.ToLinqToDBTable(), x => x);

C# Linq orderby only works for fields returned?

I want to do a Linq query that joins three tables, but only returns data from two of them (the third is only joined for ordering purposes). I'm trying to order by columns that aren't in the output of the produced query, but they seem to be ignored:
var records = from q in _pdxContext.Qualifier
join aql in _pdxContext.ApplicationQualifierLink on q.Id equals aql.QualifierId
join qt in _pdxContext.QualifierType on q.QualifierTypeId equals qt.Id
where SOME_LIST.Contains(aql.ApplicationId)
orderby aql.Sequence
select new Qualifier
{
Id = q.Id,
QualifierType = new QualifierType
{
Id = qt.Id, Value = qt.Value
}
};
return records.Distinct().ToList();
The output SQL from this does NOT have an ORDER BY clause.
If I change the orderby to read like so:
orderby q.Id
... then the output SQL has the order by clause.
Does Linq ignore orderby statements when the mentioned columns aren't used in the output (as appears to be the case here)? If so, how do I order by columns not in the output?
It seems this is an SQL limitation. The error from the SQL Server engine:
"ORDER BY items must appear in the select list if SELECT DISTINCT is specified."
So, as written, I can't do what I want to do.
I ended up using:
using (var cnn = new SqlConnection(_connectionString))
{
string sql = #"select
min(q.Id) Id, q.QualifierTypeId, q.QualifierTypeId, min(q.AcaId) AcaId,
q.QualifierTypeId Id, qt.Value
from
qdb.Qualifier q
inner join qdb.QualifierType qt on qt.Id = q.QualifierTypeId
inner join ApplicationQualifierLink l on l.QualifierId = q.id
where l.ApplicationId in (" + string.Join(",", applicationIds) + #")
group by q.Text, q.QualifierTypeId, qt.Value";
qualifiers = cnn.Query<Qualifier, QualifierType, Qualifier>(sql,
(qualifier, type) =>
{
qualifier.QualifierType = type; return qualifier;
}
).ToList();
}
Note: When you attempt to use order by and distinct as in my original clause, no error is given, entity framework silently discards the order by without any error.

Linq Left Outer Join Two Tables on Two Fields

How do I left outer join two tables on two fields in linq?
I have a sql:
select a.*, b.* from courselist as a
left outer join Summary as b
on a.subject = b.Subject and a.catalog =
b.Catalogno
where a.degree_id = 1
order by a.sequenceNo
Below is my linq query, but there is error underline "join", failed in the call to "Groupjoin". I don't know how to correct that.
var searchResults = (from a in db.courselist
join b in db.Summary on
new { a.subject,a.catalog } equals
new { b.Subject, b.Catalogno } into ab
where a.degree_id == 1
orderby a.degree_sequenceNo
from b in ab.DefaultIfEmpty()
select new
{
Courselist = a,
Summary = b
}
).ToList();
Thanks.
I've checked your code again,
I found it's fault
you just need to specify join parameters name like this:
new { suject = a.subject, catalog = a.catalog } equals
new { suject = b.subject, catalog = b.Catalogno } into ab
It seems you are missing the reference, the query doesn't have an error
try to use this:
using System.Linq;
The main issue when people start using LINQ is that they keep thinking in the SQL way, they design the SQL query first and then translate it to LINQ. You need to learn how to think in the LINQ way and your LINQ query will become neater and simpler. For instance, in your LINQ you don't need joins. You should use Associations/Navigation Properties instead. Check this post for more details.
There should be a relationship between courselist and Summary, in which case, you can access Summary through courselist like this:
var searchResults = (from a in db.courselist
where a.degree_id == 1
orderby a.degree_sequenceNo
select new {
Courselist = a,
Summary = a.Summary
}).ToList();
If there is no relationship between the two, then you should reconsider your design.

LINQ Error when using multiple JOIN in same statement on CRM 2011 Plug-in

Hi I am trying to join multiple entities in CRM 2011 but I get and error saying: {"'xrmsm_sessionEnrollments' entity doesn't contain attribute with Name = 'xrmsm_termsid'."}. That is correct but I am joining the entity that have that attribute.
My Linq Query:
var query2 = from e in svsContext.xrmsm_sessionEnrollmentsSet
join s in svsContext.xrmsm_sessionsSet on e.xrmsm_SessionLookup.Id equals s.xrmsm_sessionsId
join ic in svsContext.xrmsm_institutionCoursesSet on s.xrmsm_institutionCourseLookup.Id equals ic.xrmsm_institutionCoursesId
join ts in svsContext.xrmsm_term_sessionsSet on e.xrmsm_termSessionLookup.Id equals ts.xrmsm_term_sessionsId
join t in svsContext.xrmsm_termsSet on ts.xrmsm_TermLookup.Id equals t.xrmsm_termsId
where (e.xrmsm_StudentLookup.Equals(studentlookup)
&& e.xrmsm_YearLookup.Equals(entity.GetAttributeValue("xrmsm_studentlookup"))
&& ic.xrmsm_institutionCoursesId == institutionCourseGuid
&& t.xrmsm_termsId == termGuid)
select new { sessionName = s.xrmsm_sessionsName, StudentName = e.xrmsm_studentsName, StudentId = e.xrmsm_StudentLookup.Name };
My original SQL query that works on SQL Server:
SELECT en.xrmsm_currentsessionenrollmentsname
,en.xrmsm_isreadonlyname
,en.xrmsm_sessionenrollmentsaverage
,en.xrmsm_sessionenrollmentsgrade
,en.xrmsm_sessionenrollmentsid
,en.xrmsm_sessionenrollments_id
,en.xrmsm_sessionlookup as sessionid
,en.xrmsm_sessionlookupname
,en.xrmsm_sessionsname
,en.xrmsm_studentlookup AS studentid
,en.xrmsm_studentlookupname
,en.xrmsm_studentsname
,en.xrmsm_termsessionlookup
,en.xrmsm_termsessionlookupname
,en.xrmsm_withdrawal
,en.xrmsm_yearaverage
,en.xrmsm_yeargrade
,en.xrmsm_yearlookup
,en.xrmsm_yearlookupname
FROM CoseyTest_MSCRM.dbo.Filteredxrmsm_sessionEnrollments as en INNER JOIN
CoseyTest_MSCRM.dbo.Filteredxrmsm_sessions crmsessions ON
(en.xrmsm_sessionlookup = crmsessions.xrmsm_sessionsid AND en.xrmsm_yearlookup = crmsessions.xrmsm_yearlookup)
INNER JOIN Filteredxrmsm_institutionCourses institutionCourses
on crmsessions.xrmsm_institutioncourselookup = institutionCourses.xrmsm_institutioncoursesid
Inner Join Filteredxrmsm_term_sessions as termsession
on en.xrmsm_termsessionlookup = termsession.xrmsm_term_sessionsid
Inner Join Filteredxrmsm_terms as terms
on termsession.xrmsm_termlookup = terms.xrmsm_termsid
where en.xrmsm_yearlookup = '4BA07BED-3F51-E211-8359-00155D004403'
and en.xrmsm_studentlookup = 'C844AF65-5B51-E211-8359-00155D004403'
and terms.xrmsm_termsid = 'D1D107B7-4551-E211-8359-00155D004403'
and institutionCourses.xrmsm_institutioncoursesid = '2121914E-4551-E211-8359-00155D004403'
Linq provider for CRM has some limitations. You can fount it here. Check if your query violates limitations.
Try having a look at the actual query that it is generating and run that in SQL, it may help understand what is going on.
It could be that something your doing in LINQ is not available in CRM as paramosh mentioned but I can't see anything that jumps out at me.
Thanks for all your responses. I did the following workaround.
Make a query that retrieve a list of all the Student enrollments
Use the Find method of the List<T> class to find if a record exist with the conditions I am searching for.
var query2 = (from e in svsContext.xrmsm_sessionEnrollmentsSet
join s in svsContext.xrmsm_sessionsSet on e.xrmsm_SessionLookup.Id equals s.xrmsm_sessionsId
join ic in svsContext.xrmsm_institutionCoursesSet on s.xrmsm_institutionCourseLookup.Id equals ic.xrmsm_institutionCoursesId
join ts in svsContext.xrmsm_term_sessionsSet on e.xrmsm_termSessionLookup.Id equals ts.xrmsm_term_sessionsId
join t in svsContext.xrmsm_termsSet on ts.xrmsm_TermLookup.Id equals t.xrmsm_termsId
where (e.xrmsm_StudentLookup.Equals(studentlookup))
select new
{
EnrollmentId = e.xrmsm_sessionEnrollments_id,
SessionId = s.xrmsm_sessions_id,
EnrollmentYear = e.xrmsm_YearLookup,
InstitutionCourseId = (Guid)ic.xrmsm_institutionCoursesId,
TermId = (Guid)t.xrmsm_termsId,
Student = e.xrmsm_StudentLookup
}).ToList();
var q = query2.Find(r => r.EnrollmentYear.Id == entity.GetAttributeValue<EntityReference>("xrmsm_yearlookup").Id
&& r.InstitutionCourseId == institutionCourseGuid
&& r.TermId == termGuid);

Grouping in LINQ to Entity Model

I have following fields in entity model object
MONTH_CHAR char(1)
AVG_BALANCE int
PROD_CAT_ID int
FLG_PERS_COMM chat(1)
ACCOUNT_COUNT int
I want group by MONTH_CHAR column, I 'll write following SQL Query for this
SELECT MONTH_CHAR,
SUM(AVG_BALANCE) AS AVG_BALANCE,
MAX(PROD_CAT_ID) AS PROD_CAT_ID,
MAX(ACCOUNT_COUNT) AS ACCOUNT_COUNT,
FROM contactSummary
WHERE PROD_CAT_ID = 1
GROUP BY MONTH_CHAR
I want this query to be converted to LINQ Query.
Thanks in advance
from contact in context.Contacts
group contact by contact.Month_Char into g
select new
{
MonthChar = g.Key,
AvgBalance = g.Average(x=>x.Avg_Balance)
CatID = g.Max(x=>x.Prod_Cat_ID)
AccountCount = g.Max(x=>x.Account_Count)
}

Resources