This question already has answers here:
Check if some items are same in a c# list
(1 answer)
Group by in LINQ
(11 answers)
Closed 4 years ago.
I have a list of type ProductDetailDTO.
List<ProductDetailDTO> productDTOs;
public class ProductDetailDTO
{
public int ProductId { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public byte[] Image { get; set; }
public string Description { get; set; }
public string Brand { get; set; }
public string GUID { get; set; }
public string VariantName { get; set; }
public string VariantValue { get; set; }
public decimal Price { get; set; }
}
I have used linq to bind the data to the list.
var productDetails = (from product in ekartEntities.Products
join productImage in ekartEntities.ProductImages on product.ProductId equals productImage.ProductId
join category in ekartEntities.ProductCategories on product.Category equals category.CategoryId
join mapping in ekartEntities.ProductVariantMappings on product.ProductId equals mapping.ProductId
join variant in ekartEntities.ProductVariants on mapping.ProductVariantId equals variant.ProductVariantId
join inventory in ekartEntities.Inventories on mapping.GUID equals inventory.Guid
where product.ProductId == productDetailDTO.ProductId
select new ProductDetailDTO()
{
ProductId = product.ProductId,
Name = product.Name,
Category = category.Name,
Description = product.Description,
Brand = product.Brand,
Image = productImage.Image,
GUID = mapping.GUID.ToString(),
VariantName = variant.Name,
VariantValue = mapping.Value,
Price = inventory.Price
}).ToList();
Now, I want to display all the variants (VariantName and VariantValue) with the same GUIDs together. How can I achieve that?
You can use GroupBy and Select like this:
var variants = productDTOs
.GroupBy(k => k.GUID)
.Select(v => v
.Select(variant => new
{
variant.VariantName,
variant.VariantValue
}));
You can use Group By
group p by p.GUID into g
select new { Id = g.Key, ProductDetail = g.ToList()).ToList();
If you have tables before group by, then you can add new object in the group itself
group new { p.xyz, n.xyz }
by new { p.GUID } into g
otherwise use let to save the intermediate object in an object and do grouping on it
Related
looks like I got stuck with a nested Linq Query. I have 4 Tables which I want to join. Basically a journal has one Recipient and multiple Readers. I'd like to show the Journal with it's Recipient and all it's Readers. Here's the EF Query
var myJournals = (
from s in db.Journals
where !s.Blacklist
join recToJournals in db.RecipientsToJournals on s.JournalID equals recToJournals.JournalID
join recipients in db.Recipients on recToJournals.RecipientID equals recipients.RecipientID
join reaToJournals in db.ReadersToJournals on s.JournalID equals reaToJournals.JournalID
join readers in db.Readers on reaToJournals.ReaderID equals readers.ReaderID
select new AnalysisViewModel
{
JournalID = s.JournalID,
Title = s.Title,
RecipientName = recipients.FullName,
ReaderList = readers.FullName.ToList()
});
return View(myJournals);
Here's the ViewModel:
public class AnalysisViewModel
{
public int JournalID { get; set; }
public string Title { get; set; }
public List<Char> ReaderList { get; set; }
public string ReaderName { get; set; }
public string RecipientName { get; set; }
}
Here I'll get an Exception System.NotSupportedException: The method 'ToList' is not supported when called on an instance of type 'String'.
If I use ReaderName = readers.FullName it works, but I get a List with multiple Journals and their Readers.
How can I show only one Journal with it's Recipient and all it's Readers?
This does not make sense. Why are you calling ToList on a string? Why would you even want List<char>? Change your model so the type is of string and remove ToString
Change 1 - in your linq statement
ReaderList = readers.FullName // remove .ToList
Change 2 - in your model
public string ReaderList { get; set; }
Although it is not technically wrong it is not best practice to name a property of type string (or any non collection type for that mater) with the suffix List. A more suitable name would be ReaderName.
First of all change your ViewModel
public class AnalysisViewModel
{
public int JournalID { get; set; }
public string Title { get; set; }
public string RecipientFullName { get; set; }
public List<string> ReadersFullNames { get; set; }
}
You need GroupBy
var myJournals = from s in db.Journals
where !s.Blacklist
join recToJournals in db.RecipientsToJournals
on s.JournalID equals recToJournals.JournalID
join recipients in db.Recipients
on recToJournals.RecipientID equals recipients.RecipientID
join reaToJournals in db.ReadersToJournals
on s.JournalID equals reaToJournals.JournalID
join readers in db.Readers
on reaToJournals.ReaderID equals readers.ReaderID
select new
{
JournalID = s.JournalID,
Title = s.Title,
RecipientFullName = recipients.FullName,
ReaderFullName = readers.FullName
};
var result = myJournals.GroupBy(j => new { j.JournalID, j.Title, j.RecipientFullName })
.Select(g => new AnalysisViewModel
{
JournalID = g.Key.JournalID,
Title = g.Key.Title,
RecipientFullName = g.Key.RecipientFullName,
ReadersFullNames = g.Select(r => r.ReaderFullName).ToList(),
}
)
.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.
Hi I have following two model classes
public class c1
{
public int id { get; set; }
public int ptId { get; set; }
public int bId { get; set; }
public int rId { get; set; }
public IEnumerable<styles> newStruct { get; set; }
}
public class styles
{
public int id { get; set; }
public int bId { get; set; }
public string desc { get; set; }
}
I am trying to write a linq query
var records = (from y in db.main
join c in db.secondary on y.bId equals c.bId
where c.id == id
select new c1
{
pId= c.pId,
id = c.id,
newStruct = new List<styles>
{
new styles
{
id=y.room_id,
desc=y.desc,
}
}
});
return records.ToList();
Problem I am having is that in newStruct is suppose to be List of all the styles but it just returns one style at a time rather than one list.
Please let me know how can it return record where inside it contains list of styles
Thanks
If you want to get a sublist by main list, you should use group by,
You can try this, but I'm not sure it worked. Becasue I couldn't compile it.
var records = (from y in db.main
join c in db.secondary on y.bId equals c.bId
where c.id == id
group c by new
{
c.pId,
c.id
} into gcs
select new c1
{
pId = c.Key.pId,
id = c.Key.id,
newStruct = from g in gcs select new styles { id=g.room_id, desc=g.desc}
});
Is this LINQ to Entities? If so, and the mappings are correct in the edmx, you can try:
var records =
from c in db.secondary
where c.id == id
select new c1
{
pId = c.pId,
id = c.id,
newStruct = c.main.Select(m => new styles { id = m.room_id, desc = m.desc })
};
return records.ToList();
My models look like:
public class ReturnItem
{
public int returnItemId { get ; set; }
public int returnRequestId { get; set; }
public int quantity { get; set; }
public string item { get; set; }
}
public class ReturnRequest
{
public int returnRequestId { get; set; }
public string orderNumber { get; set; }
public IEnumerable<ReturnItem> returnItems { get; set; }
}
And I have the following query:
SELECT item, sum(quantity)
FROM ReturnItem
JOIN ReturnRequest
ON ReturnRequest.returnRequestId = ReturnItem.returnRequestId
WHERE ReturnRequest.orderNumber = '1XX'
GROUP BY item
How do I convert the query to Entity Framework and return a List<ReturnItem>? Can I use .Include instead of .Join?
from ri in db.ReturnItems
join rr in db.ReturnRequests
on ri.returnRequestId equals rr.returnRequestId
where rr.orderNumber == "1XX"
group ri by ri.item into g
select new {
Item = g.Key,
Quantity = g.Sum(i => i.quantity)
}
You can't use Include instead of Join because Include translated into Left Outer Join but you need Inner Join here.
But you can use navigation property to perform join implicitly:
db.ReturnRequests
.Where(rr => rr.orderNumber == "1XX")
.SelectMany(rr => rr.returnItems)
.GroupBy(ri => ri.item)
.Select(g => new {
Item = g.Key,
Quantity = g.Sum(ri => ri.quantity)
});
I have a linq query, which is further having a subquery, I want to store the result of that query into a user defined type, my query is
var val = (from emp in Employees
join dept in Departments
on emp.EmployeeID equals dept.EmployeeID
select new Hello
{
EmployeeID = emp.EmployeeID
Spaces = (from order in Orders
join space in SpaceTypes
on order.OrderSpaceTypeID equals space.OrderSpaceTypeID
where order.EmployeeID == emp.EmployeeID group new { order, space } by new { order.OrderSpaceTypeID, space.SpaceTypeCode } into g
select new
{
ID = g.Key.SpaceTypeID,
Code = g.Key.SpaceTypeCode,
Count = g.Count()
})
}).ToList();
Definition for my Hello class is
public class Hello
{
public IEnumerable<World> Spaces { get; set; }
public int PassengerTripID { get; set; }
}
Definition for my World class is
public class World
{
public int ID { get; set; }
public string Code { get; set; }
public int Count { get; set; }
}
You are creating anonymous object but you need to specify type name World
select new World
{
ID = g.Key.SpaceTypeID,
Code = g.Key.SpaceTypeCode,
Count = g.Count()
})