I have two entities:
public class Category
{
// Primary properties
public int Id { get; set; }
public string Name { get; set; }
// Navigation properties
public virtual ICollection<Address> Addresses { get; set; }
}
public class Address
{
// Primary properties
public int Id { get; set; }
public string Name { get; set; }
// Navigation properties
public virtual ICollection<Category> Categories { get; set; }
}
Based on a set of Address Id's, I need to Group By all the addresses by Category, including the Address Count for each Address.
Example:
Category: {1,"WORKSHOP",{1,2}},{2,"DEALER",{1,3}}
Address: {1,"Paul Workshop and Dealer",{1,2}}
{2,"Joe Workshop",{1}}
{3,"Peter Dealer",{2}}
If I have the Address Id's 1 and 3, I want to get:
Categories - "WORKSHOP - Count: 1"
"DEALER - Count: 2"
If I have the Address Id's 1 and 2, I want to get: Category -
Categories - "WORKSHOP - Count: 2"
"DEALER - Count: 1"
So far I get this, but the group by is not working:
var groupedAddresses = from add in addressQuery
where addressIds.Contains(add.Id)
group add by new { Category_Id = add.Categories, Address_Id = add.Id };
var result = from add in groupedAddresses
group add by add.Id into final
join c in categoryQuery on final.Key equals c.Id
select new CategoryGetAllBySearchDto
{
Id = final.Key,
Name = c.Name,
SearchCount = final.Count()
};
Any idea?
Thanks.
int[] addressIds = { 1, 3 };
var query = from c in categoryQuery
let searchCount = c.Addresses.Count(a => addressIds.Contains(a.Id))
where searchCount > 0
select new CategoryGetAllBySearchDto{
Id = c.Id,
Name = c.Name,
SearchCount = searchCount
};
Related
I'm currently working on a .NET 4.7 application.
Given are 2 Tables:
Table Parent Group
------------------
1 | A
2 | B
3 | C
4 | D
Table Child Group
-----------------
1 | 3 = Id from Parent Group
1 | 4 = Id from Parent Group
In my C# I get 2 classes, which are stored into lists:
public class ParentGroup
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildGroup
{
public int ParentId { get; set; }
public int ChildId { get; set; }
}
After all I query 2 lists:
List<ParentGroup> allGroupElements;
List<ChildGroup> childGroupElements;
Now I need to design a LINQ query that queries all Child Elements according to the parent Id within a method.
I thought I first iterate over all ParentElements to retrieve the children, something like this:
foreach(var item in allGroupElements){
// ... I need to query all children according to a parentId
}
Do you know how to use a LINQ query to retrieve all Child Elements with the Id of the Parent Group? And store them somehow into a new structure?
Thanks a lot!
Yes you can just use .Where in your loop
foreach(var item in allGroupElements){
var children = childGroupElements.Where(c => c.ParentId == item.Id);
}
Or you can .GroupBy, then use them
var allChildrenByParentId = children.GroupBy(c => c.ParentId);
Or you could use .Join, if you wanted parent and children in the same collection...
Use a join like this :
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<ParentGroup> allGroupElements = new List<ParentGroup>() {
new ParentGroup() { Id = 1, Name = "A"},
new ParentGroup() { Id = 2, Name = "B"},
new ParentGroup() { Id = 3, Name = "C"},
new ParentGroup() { Id = 4, Name = "D"}
};
List<ChildGroup> childGroupElements = new List<ChildGroup>() {
new ChildGroup() { ChildId = 1, ParentId = 3},
new ChildGroup() { ChildId = 1, ParentId = 4}
};
var groups = (from all in allGroupElements
join child in childGroupElements on all.Id equals child.ParentId
select new { all = all, child = child })
.ToList();
}
}
public class ParentGroup
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildGroup
{
public int ParentId { get; set; }
public int ChildId { get; set; }
}
I have a following list after joining 2 tables
Id Name IsActive FeeName Amount
1 Test 1 Fee1 100
1 Test 1 Fee2 200
1 Test 1 Fee3 300
I have a class called products
public class Products
{
public int Id { get; set; }
public string ProductName { get; set; }
public bool IsActive { get; set; }
public List<ProductFee> ProductFunding { get; set; }
}
Product fee class has FeeName and amount properties,
I need to create a object of above class something like
1,test,1,List of ProductFee
var products = results.GroupBy(r => new { r.Id, r.Name, r.IsActive }).Select(g => new Products(){ Id = g.Key.Id, ProductName = g.Key.Name, IsActive = g.Key.IsActive, ProductFunding = g.Select(p => new ProductFee(){ FeeName = p.FeeName, Amount = p.Amount }).ToList() });
Consider the following classes
public class DashboardTile
{
public int ID { get; set; }
public int? CategoryID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class DashboardTileBO : DashboardTile
{
public bool IsChecked { get; set; }
public List<DashboardTileBO> DashboardTiles { get; set; }
}
I have list of tiles in which some tiles are child of other.Now I want to show my list of tiles in such a way that if it has childs it gets added to the list.
query I am trying
var allDashBoardTiles = (from a in context.DashboardTiles
group a by a.CategoryID into b
select new BusinessObjects.DashboardTileBO
{
ID = a.ID,
Name = a.Name,
Description = b.Description,
DashboardTiles = b.ToList(),
}).ToList();
var list = context.DashboardUserTiles.Where(a => a.UserID == userId).Select(a => a.DashboardTileID).ToList();
allDashBoardTiles.ForEach(a => a.IsChecked = list.Contains(a.ID));
Now in above query when I use group clause and in select if I use a.ID,a.Name etc it says that it doesnot contain definitionor extension method for it.
Table
You can't access the properties of a directly because GroupBy returns IGrouping<TKey,T>. You can include other columns also in your group by and access them like this:-
(from a in context.DashboardTiles
group a by new { a.CategoryID, a.ID, a.Name } into b
select new BusinessObjects.DashboardTileBO
{
ID = b.Key.ID,
Name = b.Key.Name,
DashboardTiles = b.ToList(),
}).ToList();
Edit:
Also, I guess the property DashboardTiles in DashboardTileBO class should be List<DashboardTile> instead of List<DashboardTileBO>, otherwise we cannot fetch it from DashboardTiles data.
I have a list of orders and need to create groups of similar orders in an efficient manner (preferably without pulling back all orders and comparing manually).
Each order has a UserId and Email Address with additional fields of Postcode and Country.
So I need to create groups on the following rules:
If an order has the same (UserId or Email Address) and (postcode and country) place in a group
Given the following entity and data
public class Order
{
public int UserId { get; set; }
public int OrderId { get; set; }
public string Email { get; set; }
public int PostCode { get; set; }
public string Country { get; set; }
}
Example data
OrderId UserId Email PostCode Country
1 1 blah1 111 au
2 1 blah2 111 au
3 2 blah1 111 au
4 2 blah2 111 au
5 3 blah3 111 nz
6 3 blah3 111 nz
Example Results
Group 1
1 1 blah1 111 au
2 1 blah2 111 au
3 2 blah1 111 au
4 2 blah2 111 au
Group 2
5 3 blah3 111 nz
6 3 blah3 111 nz
The only way I can seem to think of doing this through manual iteration in memory
Is this possible to do with Linq to entities cleanly?
Update
After researching this for a while, I think I've come to the conclusion the only way to achieve what I want is to do two groupbys and manually combine them in memory.
Update 2
Thinking about this logically there is seemingly no elegant solution for this problem in linq and may need to be done with SQL and CTEs or some other recursive solution.
Here I have done Group by on more than 1 column,
OrderViewModel OrderList =from ord in order
group ord by new
{
ord.PostCode,
ord.Country,
ord.UserID,
ord.Email,
ord.OrderID
} into gr
select new OrderViewModel
{
OrderID = gr.Key.OrderID,
UserID = gr.Key.UserID,
Email = gr.Key.Email,
PostCode=gr.key.PostCode,
Country=gr.key.Country,
OrderList= gr.ToList()
};
where OrderViewModel is something ::
public class Order
{
public int UserId { get; set; }
public int OrderId { get; set; }
public string Email { get; set; }
public int PostCode { get; set; }
public string Country { get; set; }
public List<Order> OrderList { get; set; }
}
Where you should have to decide Priority of Grouping data,
&Data which you don't want to Group will be taken as a list.
Try this:-
var query = from ord in orders
group ord by new { ord.Country, ord.PostCode } into g
select new
{
Country = g.Key.Country,
PostCode = g.Key.PostCode,
Orders = g.GroupBy(x => x.OrderId)
.GroupBy(i => i.Count() > 1 ?
new { OrderID = i.Key, Email = default(string) }
: new { OrderID = default(int), i.First().Email })
.Select(o => o.Count() == 1 ?
new { o.Key, Orders = o.First().ToList() }
: new { o.Key, Orders = o.Select(z => z.First()).ToList() })
};
Here is the complete Working Fiddle.
Assuming your Order Class will be like below:
public class Order
{
public int UserId { get; set; }
public int OrderId { get; set; }
public string Email { get; set; }
public int PostCode { get; set; }
public string Country { get; set; }
}
Assuming and Grouping the List of Orders Like below:
public List<List<Order>> grouping()
{
// List of Orders to Group
List<Order> orderList = new List<Order>();
orderList.Add(new Order { UserId = 1, OrderId = 2007, Email = "blah1#test.com", PostCode = 111, Country = "India" });
orderList.Add(new Order { UserId = 2, OrderId = 2007, Email = "blah1#test.com", PostCode = 111, Country = "India" });
orderList.Add(new Order { UserId = 3, OrderId = 2007, Email = "blah1#test.com", PostCode = 111, Country = "India" });
orderList.Add(new Order { UserId = 4, OrderId = 2008, Email = "blah1#test.com", PostCode = 111, Country = "India" });
orderList.Add(new Order { UserId = 5, OrderId = 2008, Email = "blah1#test.com", PostCode = 111, Country = "India" });
orderList.Add(new Order { UserId = 6, OrderId = 2001, Email = "blah1#test.com", PostCode = 111, Country = "India" });
// Grouping
var groupedOrderList = orderList
.GroupBy(u => u.OrderId)
.Select(grp => grp.ToList()).ToList(); // Groping the Records based on the OrderId
return groupedOrderList; // The Result will be List<List<Order>>
}
Your group statement will group by OrderId. The Result will be come as you expected like above you showed.
Update:
You can Add additional fields as well to be grouped based on the multiple fields.
Like below :
.GroupBy(u => u.OrderId & u.UserId)
I have the following database tables:
# account_type table #
id desc
----------------
1 savings
2 checking
# account table #
id account_type_id Name
--------------------------
1 2 Don
2 1 Henry
3 1 Lisa
4 2 Jenifer
I want to write a linq query so that it returns object with collection in it, i.e.
desc: Savings { Don, Jenifer }
I created these classes:
public class acctType
{
public id { get; set; }
public string desc { get; set; }
public IEnumerable<account> account{ get; set;}
}
public class account
{
public int id { get; set; }
public int account_type_id { get; set; }
public string name { get; set;}
}
My method in api is calling:
public accType Get(int id)
{
var accounts = (from c in db.account_type
where c.p_id == id
select new accType
{
id = c.id,
name = c.desc,
account = new List<account> { name = c.desc }
});
}
return accounts.FirstOrDefault()
Problem is when I get the account object back it only has single for name i.e
dsc: checking { Don }
While answer should be Don and Jenifer. How do I fix this?
You are returning only FirstOrDefault() item,Change the return statement to
return accounts.ToList()
Edit:
public List<accType> Get(int id)
{
var accounts = (from c in db.account_type
where c.p_id == id
select new accType
{
id = c.id,
name = c.desc,
account = new List<account>()
{
name=c.desc
}
});
return accounts.ToList()
}