linq aggregate - linq

class Category
{
public string Name { get; set; }
public int Count { get; set;}
}
Name Count
AA 2
BB 3
AA 4
I have an IEnumerable<Category>
and would like to get a list of Categories with unique names and the sum of multiple entries
Output
Name Count
AA 6
BB 3
Update
class Category
{
public string Name { get; set; }
public int CountA { get; set;}
public int CountB { get; set;}
public string Phone { get; set;}
}
How would I sum two columns. and the phone column can be the last row or any row

Your updated question isn't entirely clear in terms of the phone number, but I suspect you want something like:
var query = from category in list
group category by category.Name into grouped
select new { Name = grouped.Key,
SumA = grouped.Sum(x => x.CountA),
SumB = grouped.Sum(x => x.CountB),
Phone = grouped.Last().Phone };
Changing grouped.Last() to grouped.First() would be more efficient, by the way.
Evaluating multiple aggregates in this way isn't terribly efficient in general. The Push LINQ project developed by myself and Marc Gravell makes it a lot more efficient at the cost of not being quite as easy to use. You might want to look into it if you need to deal with a lot of data.

var foo = new List<Category>() {
new Category() { Name = "AA", Count = 2},
new Category() { Name = "BB", Count = 3},
new Category() { Name = "AA", Count = 4}
};
var bar = foo.GroupBy(c => c.Name).Select(g => new Category(){ Name = g.Key, Count = g.Sum(c => c.Count) });

Related

Linq query to select any in list against a list

Using EF Core code-first, and I want to find any record with a similar list of a foreign entities to the entity I already have.
public class ClownModel {
public int Id { get; set; }
public List<CarModel> Cars { get; set; }
}
public class CarModel {
public int Id { get; set; }
}
var MyClown = new ClownModel() { /*add properties*/ }
//or maybe an existing record selected from database, just some ClownModel instance
Basically, "Select all the ClownModels where they have any Cars.Id that are in my MyClown.Cars"
Assuming that ClownModel has unique CarModel Id's, you can use the following query:
Matches All Ids
var ids = MyClown.Cars.Select(c => c.Id).ToList();
var query =
from cm in ctx.ClownModel
where cm.Cars.Where(c => ids.Contains(c.Id)).Count() == ids.Count
select cm;
Matches Any Ids
var ids = MyClown.Cars.Select(c => c.Id).ToList();
var query =
from cm in ctx.ClownModel
where cm.Cars.Where(c => ids.Contains(c.Id)).Any()
select cm;

LINQ Query for populating collection inside another collection

I am looking forward to get a linq query for populating list of teachers and their respective divisons.
Here I have 2 classes Teacher and Division which are related by DivisionGroupID - GroupID
public class Teacher
{
public int ID { get; set; }
public string Name { get; set; }
public List<Division> lstDivison {get;set;}
public int DivisionGroupID { get; set; }
}
public class Division
{
public int GroupID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
In main method List of both Teacher and Division will be populated
static void Main(string[] args)
{
Teacher obj = new Teacher { ID = 1, DivisionGroupID = 11, Name = "abcd" };
Teacher obj1 = new Teacher { ID = 2, DivisionGroupID = 12, Name = "efgh" };
List<Teacher> objList = new List<Teacher>();
objList.Add(obj);
objList.Add(obj1);
Division dv = new Division { GroupID = 11 ,Name="Division1",Description="first" };
Division dv1 = new Division { GroupID = 11, Name = "Division2", Description = "second" };
Division dv2 = new Division { GroupID = 11, Name = "Division3", Description = "third" };
Division dv3 = new Division { GroupID = 12, Name = "Division4", Description = "fourth" };
Division dv4 = new Division { GroupID = 12, Name = "Division5", Description = "fifth" };
Division dv5 = new Division { GroupID = 12, Name = "Division6", Description = "sixth" };
List<Division> lstDiv = new List<Division>();
lstDiv.Add(dv);
lstDiv.Add(dv1);
lstDiv.Add(dv2);
lstDiv.Add(dv3);
lstDiv.Add(dv4);
lstDiv.Add(dv5);
}
The requirement here is to get the list of teachers and populate the sublist of divisions each teachers holding. I got the solution based on 2 approaches.
Using sub query approach :
var upd = from teacher in objList
select new Teacher
{
ID = teacher.ID,
Name = teacher.Name,
lstDivison = (from div in lstDiv
where div.GroupID == teacher.DivisionGroupID
select new Division
{
Name = div.Name,
Description = div.Description
}).ToList()
};
Using Foeach loop through Teacher collection(objList) and updating the lstDivision
objList.ForEach(x => x.lstDivison = lstDiv
.Where(y => y.GroupID == x.DivisionGroupID)
.Select(p => new Division { Name = p.Name, Description = p.Description })
.ToList());
Both of these approaches will give me the result. But i am looking forward a better approach in as part of my project requirement which has to improve the query performance. Could you please suggest which is the best approach to handle this situation?
use yours teacher object to populate list of divisions under it. as my understanding that how it was designed class structure.
//populate property in object
objList.ForEach(x => {
x.lstDivison = lstDiv.Where(w=> w.GroupID == x.DivisionGroupID).ToList();
});
objList.Dump();

LINQ Lazy load or query incorrect

LINQ Query not populating
Model extract is as follows
public class ServiceBulletin
{
[Key]
public int Id { get; set; }
public virtual ICollection<ServiceBulletinProducts> ApplicableProducts { get; set; }
}
public class ServiceBulletinProducts
{
[Key]
public int Id { get; set; }
public int ServiceBulletinId { get; set; }
public virtual Product Product{ get; set; }
}
I'm using the following code at the moment to populate a collection
var x = from m in _dc.ServiceBulletins.Include(p => p.ApplicableProducts)
.Include(m => m.Manufacturer)
where m.DeleteStatus == DeleteStatus.Active
select m;
var x1 = new List<ServiceBulletin>();
foreach (var item in x)
{
var p = from m1 in _dc.ServiceBulletinsProducts.Include(p2=>p2.Product)
where m1.Product.DeleteStatus == DeleteStatus.Active &&
m1.ServiceBulletinId == item.Id
select m1;
var p99 = p.ToList();
item.ApplicableProducts = p99;
x1.Add(item);
};
So this is intended to have a Parent Child relationship and I’m trying to do a query which populates a collection of ServiceBulletins with a ApplicableProducts item with a fully populated collection of ServiceBulletinProducts for the ServiceBulletin with the values of the Product populated
The collection is populated but the ServiceBulletinProducts are always set to null and I can’t seem to add an Include such as .Include(p => p.ApplicableProducts.Products) to try and populate the product details – which is resulting in me iterating around the collection to populate the items.
Am I missing something to enable the population on the 1st query for the Include statement or do I need to do the query in a different way ?
Figured out the following should do the trick.
var x = from m in _dc.ServiceBulletins.Include(p => p.ApplicableProducts.Select(p2=>p2.Product))
.Include(m => m.Manufacturer)
where m.DeleteStatus == DeleteStatus.Active
select m;

Get tuple and list linked as result

I have this query :
var query = (from tables ...
where ...
select new
{
ClientName = ClientName,
ClientNumber = ClientNumber,
ClientProduct = ClientProduct
}).Distinct();
which returns rows with 3 values.
ClientName and ClientNumber can be linked to multiple products.
So we can have :
NameA NumberA Product1
NameA NumberA Product2
NameA NumberA Product3
NameB NumberB Product4
NameC NumberC Product5
I would like to know if it is possible to store that in a List of a certain class which would be like :
class MyClass
{
string ClientName,
int ClientNumber,
List<int> ClientProducts
}
So there are no duplicate of ClientName and ClientNumber.
Thank you in advance.
With this class structure to represent your data:
class MyClass
{
public string ClientName { get; set; }
public int ClientNumber { get; set; }
public List<int> ClientProducts { get; set; }
}
class Procuct
{
public string ClientName { get; set; }
public int ClientNumber { get; set; }
public int ProductID { get; set; }
}
and this test data:
List<Procuct> Products = new List<Procuct>()
{
new Procuct() { ClientName = "A", ClientNumber = 1, ProductID = 1},
new Procuct() { ClientName = "A", ClientNumber = 1, ProductID = 2},
new Procuct() { ClientName = "A", ClientNumber = 1, ProductID = 3},
new Procuct() { ClientName = "B", ClientNumber = 2, ProductID = 4},
new Procuct() { ClientName = "C", ClientNumber = 2, ProductID = 5}
};
you can use the following linq query:
var q = from p in Products
group p by new
{
cName = p.ClientName,
cNumber = p.ClientNumber
} into pGroup
select new MyClass
{
ClientName = pGroup.Key.cName,
ClientNumber = pGroup.Key.cNumber,
ClientProducts = pGroup.Select(x => x.ProductID).ToList()
};
to get exactly what you want, i.e. a collection of MyClass objects.
The Grouping performed in the above linq query essentially guarantees that there will be no duplicates on (ClientName, ClientNumber).
Since you mention Linq-to-sql, most probably you Client entity already has the products linked. You might look for an overcomplicated solution.
It depends a bit on your foreign key stucture, but if your datamodel would be
Client has 1-many product and you have a Foreign key from product to client it is already present.
So you can just reference client.Products.
So in your case it would be
var query = (from Clients...
where ...
select new
{
ClientName = Client.ClientName,
ClientNumber = Client.ClientNumber,
ClientProduct = Client.Products.Select(s=>s.id).ToList()
});
But you might as well simply use your client entity with a eager load of the products.
It all depends on your datamodel + proper foreign key structure
if you have a many-many associations like Product-per-client between your client and product you can start from that entity. Have a look at this documentation - it provides a good starting point for Linq-2-sql.
http://weblogs.asp.net/scottgu/using-linq-to-sql-part-1
I solve same problem , I think it useful to you
Only check your Where Condition properly
Thank...
var query = (from tables ...
where ...
select new
{
ClientName = ClientName,
ClientNumber = ClientNumber,
ClientProduct = ClientProduct.ToList()
}).Distinct();

GroupBy loses ThenBy sort order

How do I build an expression that will preserve the ThenBy order?
The Expression below produces the Groups ordered by Bowler.Number but the Matches of each group are not sorted.
public class Match
{
public int Id { get; set; }
public virtual Bowler Bowler { get; set; }
public byte GameNumber { get; set; }
public int Score { get; set; }
...
}
public class Bowler
{
public int Id { get; set; }
public int Number { get; set;}
...
}
var GroupedMatches = db.Matches.OrderBy(m=>m.Bowler.Number).ThenBy(m=>m.GameNumber).GroupBy(m => m.Bowler.Number)
Here is the output I want:
1
game1 295
game2 199
game3 202
game4 178
2
game1 177
...
Current I use two foreach like
foreach (var item in TheGroups){
... do some stuff with the Group
foreach (var x in item.OrderBy(a =>a.Number)) { //<-- can I get rid of this OrderBy?
... do some stuff with the Matches in this group
}
}
No big deal, I just thought LINQ would be able to help me sort the matches in the group when the groups where built, not later when I process them.
I'm not sure what you want the output to be, since it's kind of non-sensical to order a list of groups keyed on bowler number by game number.
Assuming you want an ordered list of bowler numbers, each containing an ordered list of games, something like this might work
var GroupedMatches = db.Matches
.GroupBy(m => m.Bowler.Number)
.OrderBy(g => g.Key)
.Select (g => new
{
BowlerNumber = g.Key,
Matches = g.OrderBy(m => m.GameNumber).ToList()
});
Here's specifically how you get the output you're looking for
foreach(var group in GroupedMatches) {
Console.WriteLine(group.BowlerNumber);
foreach(var match in group.Matches) {
Console.WriteLine("game{0} {1}", match.GameNumber, match.Score);
}
}

Resources