Creating a DTO model and LINQ - c#

I'm trying to create following output in ASP web API:
User[]
--> Category[]
--> Transaction[]
So I have many user with several categories and a lot of transaction linked to the category.
It seems easy but I can't get it to work due to the following problem:
My database model is the following:
//Transaction
TransactionID
Quantity
CategoryID
UserID
//Category
ID
Name
//User
ID
Name
The problem is returning a json/xml response with for example:
User1
--Cate1
----Tran1
----Tran2
--Cate2
----Tran3
User2
--Cate1
----Tran4
Because there is no separate link between User and Category only with transaction and I don't know how I can fix this with LINQ queries or something else.
--Edit
My Controller code:
List<User> Users = new List<User> {
new User {Id = 1, Name = "Matt" },
new User {Id = 2, Name = "Bill" },
new User {Id = 3, Name = "Peter" },
new User {Id = 4, Name = "Bart" }
};
List<Category> Categories = new List<Category> {
new Category {Id = 1, Name = "Sales" },
new Category {Id = 2, Name = "After Sales" },
new Category {Id = 3, Name = "Pre Sales" }
};
List<Transaction> Transactions = new List<Transaction> {
new Transaction {Id = 1, Quantity = 200, CategoryId = 1 , UserId = 1},
new Transaction {Id = 2, Quantity = 150, CategoryId = 2 , UserId = 1 },
new Transaction {Id = 3, Quantity = 300, CategoryId = 2 , UserId = 1 },
new Transaction {Id = 4, Quantity = 100, CategoryId = 1 , UserId = 2},
new Transaction {Id = 5, Quantity = 150, CategoryId = 2 , UserId = 2 },
new Transaction {Id = 6, Quantity = 250, CategoryId = 3 , UserId = 3 },
new Transaction {Id = 7, Quantity = 200, CategoryId = 1 , UserId = 4},
new Transaction {Id = 8, Quantity = 50, CategoryId = 2 , UserId = 4 },
new Transaction {Id = 9, Quantity = 250, CategoryId = 3 , UserId = 4 }
};
//(new int[] { 2, 3, 5 });
public List<UserDTO> Get()
{
var User = from d in Users
select new UserDTO
{
User = d,
/* Here I have the Problem
* I can't link the categories to the users without calling all transactions
* And then the result will for UserId = 1 will return 3 categories but 2 times After Sales and I want to return it onces
*/
Categories = (from c in Transactions
where c.UserId == d.Id
select new CategoryDTO
{
Category = c.Category,
Transactions = (from t in Transactions
where t.CategoryId == c.CategoryId && t.UserId == c.UserId
select new TransactionDTO
{
Id = t.Id,
Quantity = t.Quantity
}).ToList()
}).ToList()
};
return User.ToList();
}
All the DTO classes:
public class UserDTO
{
public User User { get; set; }
public List<CategoryDTO> Categories { get; set; }
}
public class CategoryDTO
{
public Category Category { get; set; }
public List<TransactionDTO> Transactions { get; set; }
}
public class TransactionDTO
{
public int Id { get; set; }
public int Quantity { get; set; }
}
Thanks

You'll need to group by Category in order to produce the output you want:
var User = from d in Users
select new UserDTO
{
User = d,
Categories = (from t in Transactions
where t.UserId == d.Id
group t by t.Category into g // <-- group by category
select new CategoryDTO
{
Category = g.Key,
Transactions = from ct in g
select new TransactionDTO
{
Id = ct.Id,
Quantity = ct.Quantity
}).ToList()
}).ToList()
};
return User.ToList();
Note that if your object model had navigation properties it would be a little simpler:
var User = from d in Users
select new UserDTO
{
User = d,
Categories = (from t in d.Transactions
group t by t.Category into g // <-- group by category
select new CategoryDTO
{
Category = g.Key,
Transactions = from ct in g
select new TransactionDTO
{
Id = ct.Id,
Quantity = ct.Quantity
}).ToList()
}).ToList()
};
return User.ToList();
Another option would be to use a sub-model to group transactions into categories - that might reduce some of the confusion of having users linked directly to categories (when they really belong to transactions).

Related

How to get data from 3 table into 1 list

Sorry for my bad English.
Here is my SQL Design.
I have 3 table in Sqlsever. Each table has 4 column with same name, same datatype.
And i want to get data from 4 column "Id, Name, Quantity, IdCategory" from 3 table into 1 list object same as returning value in this code below:
public async Task<IEnumerable<Shirt>> LoadAllShirt()
{
return await _dbContext.Shirt.ToListAsync();
}
I use .NET Core 6 Mvc - code first. Thanks for your help.
I have 3 table in Sqlsever. Each table has 4 column with same name,
same datatype. And I want to get data from 4 column "Id, Name,
Quantity, IdCategory" from 3 table into 1 list, I use .NET Core 6 Mvc - code first.
Well, lot of way around to handle this kind of scenario. Most easy and convenient way I would prefer to use View model or using Linq query.
Lets assume you have below Models:
Models:
public class Bags
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shirts
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shoes
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
Seeds In Models:
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
Way: 1 using ViewModel:
public class AllViewModel
{
public List<Bags> Bags { get; set; }
public List<Shirts> Shirts { get; set; }
public List<Shoes> Shoes { get; set; }
}
Query Using ViewModel:
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
Output Using ViewModel:
Way: 2 using Linq Annonymous Type:
Query Using Linq Annonymous Type:
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
Output Using Linq Annonymous Type:
Full Controller:
[HttpGet("GetFrom3Tables")]
public IActionResult GetFrom3Tables()
{
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
//Way: 1 Linq Query
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
//Way: 2 : ViewModel
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
return Ok(AllTableListUsingLinq);
}
Note: If you need more information you could check our official document for View Model and Linq Projction here
The following sample query will list your 3 types of data into a single result set.
var allResults = resultSet1.Concat(resultSet2);
For the return type create a class which will be the parent class for all your products (Bag,Shirt,Shoes) Which will help you to return data in a single Generic data.
If you use any non-generic list to send the data like hashtable or Arraylist then then there will be no issue.
In my way I will suggest to use generic data list as it will help you fetch data in better time complexity.
In this case you may need to define additional indirect base class with these 4 parameters. Than you can create Collection of this base class, and concatinate all 3 tables into.
public class BaseEntity
{
public string Name {get;set;}
}
public class Shoes : BaseEntity
{
}
...
public IEnumerable<BaseEntity> GetAllTables()
{
var shirts = await _dbContext.Shirt.ToListAsync();
var shoes = await _dbContext.Shoes.ToListAsync();
var bags = await _dbContext.Bags.ToListAsync();
return shirts.Concat(shoes).Concat(bags);
}
Similar example but witout casting to base class is shown in Enumerable.Concat documentation: https://learn.microsoft.com/pl-pl/dotnet/api/system.linq.enumerable.concat?view=net-7.0

How to use ORDER BY COUNT in LINQ and SELECT COUNT it?

I have a query and I don't know change it to LINQ
select distinct m.id,m.name, sch.id as schedule, COUNT(tk.id) as tiketSold
from movies m, schedules sch, tickets tk
where m.id = sch.movie_id and sch.id = tk.schedule_id
group by m.id,m.name, sch.id
order by COUNT(tk.id) desc
I'm trying:
var hotMovie = from m in _db.movies
from sch in _db.schedules
from tk in _db.tickets
where m.id == sch.movie_id && sch.id == tk.schedule_id
group m by m.id into g
orderby g.Count()
select new { Movie = g};
I do not have your database, so, I have created 3 classes like your table as I can anticipate. Then I have created 3 list like you table in the "TestMethod". In the linq query, I have joined the 3 list as you shown in sql query segment "where m.id = sch.movie_id and sch.id = tk.schedule_id" and then I perform the group by, order by an select. Here is my code, please try it and let me know it works or not.
public class movies
{
public int id { get; set; }
public string name { get; set; }
}
public class schedules
{
public int id { get; set; }
public int movie_id { get; set; }
}
public class tickets
{
public int id { get; set; }
public int schedule_id { get; set; }
}
void TestMethod()
{
//Add Movies to the list
List<movies> moviesItems = new List<movies>();
moviesItems.Add(new movies() { id = 1, name = "A" });
moviesItems.Add(new movies() { id = 2, name = "B" });
//Add Schedules to the list
List<schedules> schedulesItems = new List<schedules>();
schedulesItems.Add(new schedules() { id = 1, movie_id = 1 });
schedulesItems.Add(new schedules() { id = 2, movie_id = 2 });
schedulesItems.Add(new schedules() { id = 3, movie_id = 1 });
schedulesItems.Add(new schedules() { id = 4, movie_id = 2 });
//Add Tickets to the list
List<tickets> ticketsItems = new List<tickets>();
ticketsItems.Add(new tickets() { id = 1, schedule_id = 1 });
ticketsItems.Add(new tickets() { id = 2, schedule_id = 1 });
ticketsItems.Add(new tickets() { id = 3, schedule_id = 2 });
ticketsItems.Add(new tickets() { id = 4, schedule_id = 2 });
ticketsItems.Add(new tickets() { id = 5, schedule_id = 2 });
ticketsItems.Add(new tickets() { id = 6, schedule_id = 3 });
ticketsItems.Add(new tickets() { id = 7, schedule_id = 3 });
ticketsItems.Add(new tickets() { id = 8, schedule_id = 3 });
ticketsItems.Add(new tickets() { id = 9, schedule_id = 3 });
ticketsItems.Add(new tickets() { id = 10, schedule_id = 4 });
var query = from final in (from m in moviesItems
join sch in schedulesItems on m.id equals sch.movie_id
join tk in ticketsItems on sch.id equals tk.schedule_id
select new { movieID = m.id, movieName = m.name, schID = sch.id, tkID = tk.id })
group final by new { final.movieID, final.movieName, final.schID } into g
orderby g.Count() descending
select new { g.Key.movieID, g.Key.movieName, g.Key.schID, tiketSold = g.Count() };
}
This query is closest to your SQL but probably you need LEFT JOIN. Also it can be simplified using navigation properties if you provide model.
var hotMovie =
from m in _db.movies
join sch in _db.schedules on m.id equals sch.movie_id
join tk in _db.tickets on sch.id equals tk.schedule_id
group tk by new { movieID = m.id, movieName = m.name, scheduleId = sch.id } into g
orderby g.Sum(x => x.id != null ? 1 : 0) descending
select new
{
g.Key.movieID,
g.Key.movieName,
g.Key.scheduleId,
tiketSold = g.Sum(x => x.id != null ? 1 : 0)
};

What is the Linq Query expression to get all the department Id , Name in a select list variable for drop down

I am trying to create the drop down to list the Department name having right to see for the login user.I am passing the userId, DepotIds. The department must be listed against the user and Depot. My Linq query is not working, please help
I have the following model
public class Depot
{
public int Id { get; set; }
public string DepotName { get; set; }
}
public class Department
{
public int Id { get; set; }
public string DepartmentName { get; set; }
}
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
}
public class USerDepotDepartmentLink
{
public int UserId { get; set; }
public int DepotId { get; set; }
public int DepartmentId { get; set; }
public IsDefault { get; set; }
}
From the above model I have the following records
Depot Record
Id = 1; DepotName = Depot1
Id = 2 ; DepotName = Depot2
Department Record
Id = 1; DepartmentName = Sales
Id = 2 ; DepartmentName = Account
Id = 3 ; DepartmentName = Marketing
User Record
Id = 1; Username = User1
Id = 2; Username = User2
USerDepotDepartmentLink
UserId = 1, DepotId=1, DepartmentId =1 , IsDefault = 1
UserId = 1, DepotId=1, DepartmentId =2 , IsDefault = 0
UserId = 2, DepotId=1, DepartmentId =2 , IsDefault = 0
UserId = 2, DepotId=1, DepartmentId =3 , IsDefault = 0
UserId = 2, DepotId=2, DepartmentId =1 , IsDefault = 0
UserId = 2, DepotId=2, DepartmentId =2 , IsDefault = 1
UserId = 2, DepotId=2, DepartmentId =3 , IsDefault = 0
from the above example for the UserId 1 The dropdown of the Department down list must be 'Sales, Accounts' and selected 'Sales department'
For the userId 2 , the Department drop down list must be 'Sales, Accounts,Marketing and selected Department is Account.
I created the Linq query given below but not working
public IEnumerable<SelectListItem> GetLocationsByDepotForDropdown(int userId, int[] depotNo)
{
List<SelectListItem> locations = (from dpt in goContext.goDepartment
join dep in goContext.goUserDepartment
on dpt.DepartmentID equals dep.DepartmentID
where dep.UserID == userId
&& dpt.IsDeleted == false
select new SelectListItem
{
Value = dpt.DepartmentID.ToString(),
Text = dpt.DepartmentName
}).Where(i => depotNo.Contains(i.Value)).
ToList<SelectListItem>();
locations.Insert(0, new SelectListItem
{
Value = "0",
Text = "-- Select --"
});
return locations;
}
Please help to find the linq query from my example
Please refer to the following sample code, you could use GroupBy clause to remove the duplicate records (based on the text and value property), and then check whether the group items contain the selected value (True: IsDefault is 1; False: IsDefault is 0):
var user = "User 2";
var result = (from udd in usddlist
join u in userlist on udd.UserId equals u.Id
join d in departmentlist on udd.DepartmentId equals d.Id
where u.UserName == user
select new
{
Value = d.Id.ToString(),
Text = d.DepartmentName,
IsSelected = udd.IsDefault == 1 ? true : false
}).GroupBy(c => new { c.Text, c.Value })
.Select(c =>
new SelectListItem
{
Value = c.Key.Value,
Text = c.Key.Text,
Selected = c.Where(d => d.IsSelected == true).ToList().Count == 0 ?false : true
})
.Distinct().ToList();
The Initial data :
List<Depot> depotlist = new List<Depot>()
{
new Depot(){ Id=1, DepotName="Depot 1"},
new Depot(){ Id=2, DepotName="Depot 2"}
};
List<Department> departmentlist = new List<Department>()
{
new Department(){ Id=1, DepartmentName="Sales"},
new Department(){ Id=2, DepartmentName="Account"},
new Department(){ Id=3, DepartmentName="Marketing"},
};
List<User> userlist = new List<User>()
{
new User(){ Id=1, UserName="User 1"},
new User(){ Id=2, UserName="User 2"}
};
List<USerDepotDepartmentLink> usddlist = new List<USerDepotDepartmentLink>()
{
new USerDepotDepartmentLink(){ UserId = 1, DepotId = 1, DepartmentId = 1,IsDefault=1},
new USerDepotDepartmentLink(){ UserId = 1, DepotId = 1, DepartmentId = 2,IsDefault=0},
new USerDepotDepartmentLink(){ UserId = 2, DepotId = 1, DepartmentId = 2,IsDefault=0},
new USerDepotDepartmentLink(){ UserId = 2, DepotId = 1, DepartmentId = 3,IsDefault=0},
new USerDepotDepartmentLink(){ UserId = 2, DepotId = 2, DepartmentId = 1,IsDefault=0},
new USerDepotDepartmentLink(){ UserId = 2, DepotId = 2, DepartmentId = 2,IsDefault=1},
new USerDepotDepartmentLink(){ UserId = 2, DepotId = 2, DepartmentId = 3,IsDefault=0},
};
After executing the above code, the result as below (the selected Department is Account, Sales and Marketing's Select property is "false"):
If you want to sort the DropDownlist items, after filter data, you could use OrderBy() method to sort the SelectList items.
You can use the below query which would gives the unique department and also the required option can be selected
List<SelectListItem> locations = (from dpt in goContext.goDepartment
join dep in goContext.goUserDepartment
on dpt.Id equals dep.DepartmentId
where dep.UserId == userId && depotNo.Contains(dep.DepotId)
select new
{
DepartmentId = dep.DepartmentId,
DepartmentName = dpt.DepartmentName
}).Distinct()
.Select(s => new SelectListItem
{
Value = s.DepartmentId.ToString(),
Text = s.DepartmentName,
// Selected = write your logic here based on condition
})
.ToList<SelectListItem>();

How to make nested list from one base list

I would like to make nested list from this one list
public class Product
{
string Id;
string ProductName;
decimal Price;
string Supplier;
int Quantity;
string VersionId;
string TypeId;
}
public class ProductTypeDto
{
public string TypeId { get; set; }
public string ProductName { get; set; }
public string Price { get; set; }
public List<ProductVersionDto> ProductVersions { get; set; }
}
public class ProductVersionDto
{
public string VersionId { get; set; }
public string ProductName { get; set; }
public string Supplier { get; set; }
public int Quantity { get; set; }
}
I would like to know how I can create a list of ProductTypeDto using linq c# .
I need to get all products with the same TypeId , and ProductVersions field should contain products with same version Id (and of course same TypeId).
I don't want to use foreach loops, and I dont want to loop over products twice to make this nested list.. I think there would be a better way using Linq, would be great if you can help..
Edit: I add here what I have done so far, but it is not the way I want this to be fixed.
List<ProductTypeDto> products = this._dbContext
.Products
.Where(product => product.TypeId == query.TypeId)
.Select(product => new ProductTypeDto()
{
TypeId = product.TypeId,
ProductName = product.ProductName,
Price = product.Price,
ProductVersions = product.Products.Where(p => p.TypeId == product.TypeId)
.Select(p => new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
}).ToList()
})
.ProjectTo<ProductTypeDto>(this._config)
.ToListAsync(cancellationToken);
This is the result I want to get:
var product1 = new Product() { Id = 1, ProductName = "foo", Price = 20, Supplier = "test1", Quantity = 3, VersionId = "1", TypeId = "1" };
var product2 = new Product() { Id = 2, ProductName = "foo1", Price = 60, Supplier = "test2", Quantity = 9, VersionId = "1", TypeId = "1" };
var product3 = new Product() { Id = 3, ProductName = "foo2", Price = 30, Supplier = "test3", Quantity = 5, VersionId = "2", TypeId = "1" };
var product4 = new Product() { Id = 4, ProductName = "foo3", Price = 10, Supplier = "test4", Quantity = 4, VersionId = "1", TypeId = "2" };
var product5 = new Product() { Id = 5, ProductName = "foo4", Price = 50, Supplier = "test5", Quantity = 8, VersionId = "1", TypeId = "3" };
List<ProductVersionDto> p1 = {
new ProductVersionDto { ProductName = "foo", Quantity= 3, Supplier ="test1"}
new ProductVersionDto { ProductName = "foo1", Quantity= 9, Supplier ="test2"}
};
List<ProductVersionDto> p2 = {
new ProductVersionDto { ProductName = "foo3", Quantity= 4, Supplier ="test4"}
};
List<ProductVersionDto> p3 = {
new ProductVersionDto { ProductName = "foo4", Quantity= 8, Supplier ="test5"}
};
List<ProductTypeDto> products = {
new ProductTypeDto{ ProductName = "foo", Price =20, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo1", Price =60, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo3", Price =10, ProductVersions = p2}
new ProductTypeDto{ ProductName = "foo4", Price =50, ProductVersions = p3}
}
Try this:
var dtos =
(
from p in products
group new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
} by new { p.TypeId, p.ProductName, p.Price } into g
select new ProductTypeDto()
{
TypeId = g.Key.TypeId,
ProductName = g.Key.TypeId,
Price = g.Key.Price,
ProductVersions = g.ToList(),
}
).ToList();
It appears that you meant Price to be a decimal in ProductTypeDto, BTW.

Using LINQ to group a list of objects

I have an object:
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
}
I return a list that may look like the following:
List<Customer> CustomerList = new List<Customer>();
CustomerList.Add( new Customer { ID = 1, Name = "One", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 2, Name = "Two", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 3, Name = "Three", GroupID = 2 } );
CustomerList.Add( new Customer { ID = 4, Name = "Four", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 5, Name = "Five", GroupID = 3 } );
CustomerList.Add( new Customer { ID = 6, Name = "Six", GroupID = 3 } );
I want to return a linq query which will look like
CustomerList
GroupID =1
UserID = 1, UserName = "UserOne", GroupID = 1
UserID = 2, UserName = "UserTwo", GroupID = 1
UserID = 4, UserName = "UserFour", GroupID = 1
GroupID =2
UserID = 3, UserName = "UserThree", GroupID = 2
GroupID =3
UserID = 5, UserName = "UserFive", GroupID = 3
UserID = 6, UserName = "UserSix",
I tried from
Using Linq to group a list of objects into a new grouped list of list of objects
code
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID)
.Select(grp => grp.ToList())
.ToList();
works but does not give the desired output.
var groupedCustomerList = CustomerList.GroupBy(u => u.GroupID)
.Select(grp =>new { GroupID =grp.Key, CustomerList = grp.ToList()})
.ToList();
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID, u=>{
u.Name = "User" + u.Name;
return u;
}, (key,g)=>g.ToList())
.ToList();
If you don't want to change the original data, you should add some method (kind of clone and modify) to your class like this:
public class Customer {
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
public Customer CloneWithNamePrepend(string prepend){
return new Customer(){
ID = this.ID,
Name = prepend + this.Name,
GroupID = this.GroupID
};
}
}
//Then
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID, u=>u.CloneWithNamePrepend("User"), (key,g)=>g.ToList())
.ToList();
I think you may want to display the Customer differently without modifying the original data. If so you should design your class Customer differently, like this:
public class Customer {
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
public string Prefix {get;set;}
public string FullName {
get { return Prefix + Name;}
}
}
//then to display the fullname, just get the customer.FullName;
//You can also try adding some override of ToString() to your class
var groupedCustomerList = CustomerList
.GroupBy(u => {u.Prefix="User", return u.GroupID;} , (key,g)=>g.ToList())
.ToList();
is this what you want?
var grouped = CustomerList.GroupBy(m => m.GroupID).Select((n) => new { GroupId = n.Key, Items = n.ToList() });
var result = from cx in CustomerList
group cx by cx.GroupID into cxGroup
orderby cxGroup.Key
select cxGroup;
foreach (var cxGroup in result) {
Console.WriteLine(String.Format("GroupID = {0}", cxGroup.Key));
foreach (var cx in cxGroup) {
Console.WriteLine(String.Format("\tUserID = {0}, UserName = {1}, GroupID = {2}",
new object[] { cx.ID, cx.Name, cx.GroupID }));
}
}
The desired result can be obtained using IGrouping, which represents a collection of objects that have a common key in this case a GroupID
var newCustomerList = CustomerList.GroupBy(u => u.GroupID)
.Select(group => new { GroupID = group.Key, Customers = group.ToList() })
.ToList();

Categories

Resources