Grouping in LINQ to Entity Model - linq

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

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

Group by with count on multiple table in 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
....
}

Get Date part Using LINQ

I have four tables, with Date data type for the fields startingDate, EndingDate, and ApplyingDate.
I am using ADO.net Entity Framework.
I have written the following query to get the results, but I am getting the dates with the time, and I want only the date part.
I have used EntityFunctions.TuncateTime, but I am still getting same results.
Could anyone please suggest me, how to Get the date only ?
var leaveList = (from application in db.tbl_ApplicationData
join employee in db.tbl_EmployeeDetails
on application.UserName equals employee.UserName
join leaveType in db.tbl_LeaveType
on application.LeaveTypeId equals leaveType.LeaveTypeId
join status in db.tbl_Status
on application.ApplicationStatusId equals status.StatusId
where application.UserName == "100083"
select new
{
EmployeeName = employee.EmployeeName,
LeaveTypeID = leaveType.LeaveTypeName,
StartingDate = EntityFunctions.TruncateTime(application.StartingDate),
EndingDate = EntityFunctions.TruncateTime(application.EndingDate),
AppliedDate = EntityFunctions.TruncateTime(application.ApplyingDate),
NoOfDays = application.NoOfDays,
LeavePurpose = application.LeavePurpose,
LeaveStatus = status.StatusName
});
If your entity model is a System.DateTime, you can just use the DateTime methods when you are using your object:
select new {
EndingDate = application.EndingDate
};
var myValue = leaveList.EndingDate.Date;
Or if you want a string:
leaveList.EndingDate.ToShortDateString()

Dynamic Linq Library can’t handling duplicate alias column names

I am trying to collect the data from database by using Dynamic Linq Library NeGet. When I loop through it showing this error ‘The item with identity 'FirstName' already exists in the metadata collection’
Seems like Dynamic Linq Library NuGet is can’t handle duplicate alias column names.
I have two tables and it has One-On-Many relationship as follow, containing the same Columns names in Lead table and CoBorrower table.
Table1: Lead
Columns: LeadID, FirstName,DateCreated
Table2: CoBorrower
Columns: LeadID, CoBorrowerID,FirstName,Tax,DateCreated
Here is my code snippet
var res = (from l in db.Leads
join db.CoBorrower.GetAll()
on l.LeadID equals cb.LeadID
select new { l, cb }).AsQueryable();
string myCustomCondition="FistName=myname";
IQueryable iq = res.Where(myCustomCondition)
.OrderBy(reportBulder.Group1)
.Select("new(l.LeadID,l.FirstName,cb.FistName)")
.GroupBy("LeadID", "it")
.Select("new (it.Key as Key, it as Value)");
foreach (dynamic group in iq)
{
string Key = group.Key.ToString();
List<dynamic> items = new List<dynamic>();
foreach (dynamic album in group.Value)
{
items.Add(album);
}
dataList.Add(Key, items);
}
I will appreciate your help in advance.
This is logical. The .Select("new(l.LeadID,l.FirstName,cb.FistName)") will create an anonymous object like:
new
{
LeadID = ....,
FirstName = ....,
FirstName = ....,
}
that is illegal (two properties with the same name)
Use the as
.Select("new(l.LeadID,l.FirstName,cb.FistName as FirstName2)")
so that the anonymous object created is
new
{
LeadID = ....,
FirstName = ....,
FirstName2 = ....,
}
as you do in the second .Select.

Linq extract a count() value from a data object

I have divAssignments that has potential multiple rows by rNI, an official id, according to a compound key of Indictment and booking numbers.
rNI Booking Indictment
12345 954445 10 12345
12345 954445 10 12346
12345 954445 10 12347
So ID has a count of 3 for a single booking number for this rni.
I get lost attempting to generate a count and a group by booking Number:
var moreThen = from dA in divAssignments
select new { dA.rNI, IndictmentCount = dA.indictmentNumber.Count() };
Most of the examples are dealing with static int[] and don't seem to work in my case.
How do I get a group and then a count? If I could put in a having that would be fantastic.
from a t-sql POV I'd use this:
Select rni, bookingNumber, count(*) IndictmentCount
from divAssignments
group by rni, bookingNumber
having count(*) > 0
TIA
How about something like this:
var query = from item in divAssignments
group item by item.rNI into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count()
}
If you're interested in grouping by both the rNI and the booking number, I would change it to this:
var query = from item in divAssignements
group item by new { item.rNI, a.Booking } into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count
};
OR
var query = from item in divAssignments
group item by item into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count()
}
and implement IEquatable on the divAssignment object to support equality comparison. The other option if you'd like is to write an IEqualityComparer instance to do the composite key comparison. Your query could then look like:
var query =
divAssignments
.GroupBy(i => i, new MyCustomEqualityComparer())
.Select(i => new { Key = i.Key, Count = i.Count());
var query =
from dA in divAssignments
group dA by new { dA.rNI, dA.bookingNumber };
foreach(var grp in query)
{
Console.WriteLine("rNI={0}, bookingNumber={1} => Count={2}", grp.Key.rNI, grp.Key.bookingNumber, grp.Count());
}
If you use a Grouping operator in Linq you will get what you need. The code:
var count = from a in divAssignments
group a by new { a.rNI, a.Booking } into b
select b;
will return a collection of IGrouping objects. This will give you the Key (in my example this will be an anonymous type with an rNI and a Booking property) and a collection of the divAssignments that match the key.
Using Method syntax (much easier to read in my opinion):
First group the records, then select a new result for each group that contains the count.
var groups = divAssignments.GroupBy(d => new { d.rNI, d.Booking });
groups.Select(g=> new { g.Key.rNI, g.Key.Booking, IndictmentCount = g.Count() });

Resources