LINQ to get unique id that has list of items - c#

I am trying to generate a list result through linq.
I would like to have a result as a list with unique folder id with 0th item as folder_name, 1st Item as a list with one or more projects having fields project_id,name and description.
I have written following query:
Folders is basically model with format as folderid, name, List projects where Project Model has project_id, name and description
from the following records:
Models
public class FolderModel
{
public int folder_id { get; set; }
public string folder_name { get; set; }
public List<ProjectModel> projects{ get; set; }
}
public class ProjectModel
{
public int project_id { get; set; }
public string project_name { get; set; }
public string project_description { get; set; }
}
public class ResultModel
{
public List<FolderModel> folders { get; set; }
}
Result Data
List<FolderModel, List<ProjectModel>> result = new List<FolderModel, List<ProjectModel>>();
List<ProjectModel> projectList1 = new List<>();
ProjectModel projectModel1 = new ProjectModel();
projectModel1.project_name = "F1P1";
projectModel1.project_description = "F1P1";
projectList1.add(projectModel1);
List<ProjectModel> projectList2 = new List<>();
ProjectModel projectModel21 = new ProjectModel();
projectModel21.project_name = "F2P1";
projectModel21.project_description = "F2P1";
projectList2.add(projectModel21);
ProjectModel projectModel22 = new ProjectModel();
projectModel22.project_name = "F2P2";
projectModel22.project_description = "F2P2";
projectList2.add(projectModel22);
List<ProjectModel> projectList3 = new List<>();
ProjectModel projectModel3 = new ProjectModel();
projectModel3.project_name = "F3P1";
projectModel3.project_description = "F1P3";
projectList3.add(projectModel3);
ResultModel resultModel = new resultModel();
resultModel.(new FolderModel { folder_id: 1,folder-name: "F1" }, projectList1);
FolderModel folderModel1 = new FolderModel();
folderModel1.folder_id = 1
folderModel1.folder_name = "F1"
folderModel1.projects = projectList1
FolderModel folderModel2 = new FolderModel();
folderModel2.folder_id = 2
folderModel2.folder_name = "F2"
folderModel2.projects = projectList2
FolderModel folderModel3 = new FolderModel();
folderModel3.folder_id = 3
folderModel3.folder_name = "F3"
folderModel3.projects = projectList3
ResultModel resultModel = new ResultModel();
List<FolderModel> folderList = new List<>();
folderList.add(folderModel1);
folderList.add(folderModel2);
folderList.add(folderModel3);
resultModel.folders = folderList
SQL Data
folder_id | folder_name | project_id | project_name | project_description
1 F1 11 F1P1 F1P1
2 F2 21 F2P1 F2P1
2 F2 22 F2P2 F2P2
3 F3 31 F3P1 F3P1
4 F4 41 F4P1 F4P1
5 F5 51 F5P1 F5P1
This is what I have tried
var result = resultModel.folders.GroupBy(x => new { x.folder_id }).ToList();
I am sure that after group by I have to select name but not sure how can I generate project into a list and add it to main folder id. Can someone please guide on this.

You can query like this:
var result =
resultModel
.folders
.GroupBy(x => new { x.folder_id })
.Select(s => new
{
folder_id = s.Key,
folder_name = s.First().folder_name
})
.ToList();

It seems to me that you're looking for this:
var folders = new []
{
new { folder_id = 1, folder_name = "F1", project_id = 11, project_name = "F1P1", project_description = "F1P1" },
new { folder_id = 2, folder_name = "F2", project_id = 21, project_name = "F2P1", project_description = "F2P1" },
new { folder_id = 2, folder_name = "F2", project_id = 22, project_name = "F2P2", project_description = "F2P2" },
new { folder_id = 3, folder_name = "F3", project_id = 31, project_name = "F3P1", project_description = "F3P1" },
new { folder_id = 4, folder_name = "F4", project_id = 41, project_name = "F4P1", project_description = "F4P1" },
new { folder_id = 5, folder_name = "F5", project_id = 51, project_name = "F5P1", project_description = "F5P1" },
};
List<FolderModel> result =
folders
.GroupBy(
x => new { x.folder_id, x.folder_name },
x => new { x.project_id, x.project_name, x.project_description })
.Select(x => new FolderModel()
{
folder_id = x.Key.folder_id,
folder_name = x.Key.folder_name,
projects = x.Select(y => new ProjectModel()
{
project_id = y.project_id,
project_name = y.project_name,
project_description = y.project_description,
}).ToList(),
})
.ToList();

Related

How to convert dynamic to unknown class in runtime

I have a dynamic rule engine and i want to pass class to this and each time the class is sent differently.
For example:
Order MyOrder = new Order()
{
OrderId = 1,
Customer = new Customer()
{
FirstName = "John",
LastName = "Doe",
Country = new Country()
{
CountryCode = "AUS"
}
},
Items = new List<Item>(){
new Item(){ ItemCode = "MM23", Cost=5.25M},
new Item(){ ItemCode = "LD45", Cost=5.25M},
new Item(){ ItemCode = "Test", Cost=3.33M},
}
};
I want to change this:
var compiledRule = engine.CompileRule<Order>(rule);
to :
dynamic obj = MyOrder;
var compiledRule = engine.CompileRule<?????>(rule);
how can I get Type of obj and put instead of "????"
I found solution after search a lot
var engine = new MRE();
var compiledRule = engine.CompileRule<Order>(rule);
change to:
var engine = new MRE();
var compiledRule = typeof(MRE).GetMethod("CompileRule").MakeGenericMethod(myOrder.GetType())
.Invoke(engine, new object[] { rule}) as dynamic;

Dynamic List in Entity FrameWork WebApi 2.0

Im using DTO's in EntityFrameWork with WebApi 2.0 , so I want to retrieve all the Orders, within the Orders, OrderProducts is a list in my program, I want to retrieve all the OrderProducts related to that Order my code right now is the following:
public async Task < IHttpActionResult > GetOrder() {
var order = from x in db.Order
select new OrderDTO {
OrderId = x.OrderId,
UserId = x.UserId,
orderStatusCode = x.orderStatusCode,
OrderProducts = new List < OrderProductDTO > {
new OrderProductDTO {
OrderId = x.OrderProducts.Select(y = >y.OrderId).FirstOrDefault(),
OrderProductId = x.OrderProducts.Select(y = >y.OrderProductId).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.ProductId).FirstOrDefault(),
Product = new ProductDTO() {
productDesc = x.OrderProducts.Select(y = >y.Product.productDesc).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.Product.ProductId).FirstOrDefault(),
productName = x.OrderProducts.Select(y = >y.Product.productName).FirstOrDefault(),
productPrice = x.OrderProducts.Select(y = >y.Product.productPrice).FirstOrDefault(),
}
}
},
purchaseDate = x.purchaseDate,
quantityOrder = x.quantityOrder,
totalOrderPrice = x.totalOrderPrice,
User = new UserDTO {
UserId = x.UserId,
username = x.User.username,
userInfo = new UserInfoDTO {
adress = x.User.UserInfo.adress,
city = x.User.UserInfo.city,
country = x.User.UserInfo.country,
zip = x.User.UserInfo.zip
}
}
};
return Ok(order);
Everything appears to be ok, but when I call the WebApi only the first element is returned, not all the elements in OrderProduct:
Any idea how to retrieve all the OrderProducts? Thanks.
Well you're only populating a single item in your query. Instead, you should do this:
....
OrderProducts = x.OrderProducts.Select(op => new OrderProductDTO
{
OrderId = op.OrderId,
OrderProductId = op.OrderProductId,
//etc
}
....
It looks like you're only asking for one Product instead of a List
Product = new ProductDTO() {
productDesc = x.OrderProducts.Select(y = >y.Product.productDesc).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.Product.ProductId).FirstOrDefault(),
productName = x.OrderProducts.Select(y = >y.Product.productName).FirstOrDefault(),
productPrice = x.OrderProducts.Select(y = >y.Product.productPrice).FirstOrDefault(),
}
Should probably be
Products = new List<ProductDTO>() {...}

How to define in the lambda expression as another function in LINQ Select Method

I am creating Azure Mobile app.
In the api I created following list with Entity Framework 6.1.
The problem is that it is too big in the Select methods,
public IHttpActionResult GetAllQABundle(string qAUser_id, int offset = 0, int limit = 20)
{
List<QABundleWithCommentDto> qABundleWithCommentDtos = context.QABundles
.Where(b => b.TeamId == null)
.OrderByDescending(b => b.UpdatedAt)
.Skip(offset)
.Take(limit)
.Select(b => new QABundleWithCommentDto()
{
Id = b.Id,
TagForFreeFormat = b.TagForFreeFormat,
MovieUrl = b.Movie.MovieUrl,
MovieThumbnailUrl = b.Movie.MovieThumbnailUrl,
MovieStreamUrl = b.Movie.MovieStreamUrl,
NumberOfViews = b.Movie.NumberOfViews,
Title = b.Title,
Description = b.Description,
QuestionType = b.QuestionType,
WannaKnowId = b.WannaKnows.Where(w => w.QAUserId == qAUser_id).FirstOrDefault().Id,
WannaKnowCount = b.WannaKnows.Count,
QAUserThumbnailUrl = b.QAUser.ThumbnailUrl,
QAUserId = b.QAUser.Id,
UserName = b.QAUser.UserName,
UpdatedAt = b.UpdatedAt,
GenereDtos = b.Generes.Select(t => new GenereDto() { GenereId = t.Id, GenereName = t.Name }).ToList(),
CommentDtos = b.Comments.OrderByDescending(c => c.UpdatedAt).Take(20).Select(c => new CommentDto()
{
Id = c.Id,
Text = c.Text,
MovieUrl = c.Movie.MovieUrl,
MovieThumbnailUrl = c.Movie.MovieThumbnailUrl,
QAUserId = c.QAUserId,
UserName = c.QAUser.UserName,
QAUserBelongsTo = c.QAUser.BelongsTo,
QAUserThumbnailUrl = c.QAUser.ThumbnailUrl,
CommentCreatedAt = c.CreatedAt,
Likes = c.Likes.Count,
LikeId = c.Likes.Where(x => x.QAUserId == qAUser_id).FirstOrDefault().Id,
UpdatedAt = c.UpdatedAt,
QABundleId = c.QABundleId
}).ToList(),
TeamDto = new TeamDto()
{
Id = b.TeamId,
Name = b.Team.Name,
FollowedDtos = b.Team.QAUsers.Select(u => new FollowedDto()
{
Id = u.Id,
UserName = u.UserName,
ThumbnailUrl = u.ThumbnailUrl,
}).ToList()
},
BestAnswerDto = new BestAnswerDto() { Id = b.BestAnswerId, CommentId = b.BestAnswer.CommentId }
})
.ToList();
return Json(qABundleWithCommentDtos);
}
I would like to define following part as another function, but I do not know how I implement that.
Does anyone have good idea?
b => new QABundleWithCommentDto()
{
Id = b.Id,
TagForFreeFormat = b.TagForFreeFormat,
MovieUrl = b.Movie.MovieUrl,
MovieThumbnailUrl = b.Movie.MovieThumbnailUrl,
MovieStreamUrl = b.Movie.MovieStreamUrl,
NumberOfViews = b.Movie.NumberOfViews,
Title = b.Title,
Description = b.Description,
QuestionType = b.QuestionType,
WannaKnowId = b.WannaKnows.Where(w => w.QAUserId == qAUser_id).FirstOrDefault().Id,
WannaKnowCount = b.WannaKnows.Count,
QAUserThumbnailUrl = b.QAUser.ThumbnailUrl,
QAUserId = b.QAUser.Id,
UserName = b.QAUser.UserName,
UpdatedAt = b.UpdatedAt,
GenereDtos = b.Generes.Select(t => new GenereDto() { GenereId = t.Id, GenereName = t.Name }).ToList(),
CommentDtos = b.Comments.OrderByDescending(c => c.UpdatedAt).Take(20).Select(c => new CommentDto()
{
Id = c.Id,
Text = c.Text,
MovieUrl = c.Movie.MovieUrl,
MovieThumbnailUrl = c.Movie.MovieThumbnailUrl,
QAUserId = c.QAUserId,
UserName = c.QAUser.UserName,
QAUserBelongsTo = c.QAUser.BelongsTo,
QAUserThumbnailUrl = c.QAUser.ThumbnailUrl,
CommentCreatedAt = c.CreatedAt,
Likes = c.Likes.Count,
LikeId = c.Likes.Where(x => x.QAUserId == qAUser_id).FirstOrDefault().Id,
UpdatedAt = c.UpdatedAt,
QABundleId = c.QABundleId
}).ToList(),
TeamDto = new TeamDto()
{
Id = b.TeamId,
Name = b.Team.Name,
FollowedDtos = b.Team.QAUsers.Select(u => new FollowedDto()
{
Id = u.Id,
UserName = u.UserName,
ThumbnailUrl = u.ThumbnailUrl,
}).ToList()
},
BestAnswerDto = new BestAnswerDto() { Id = b.BestAnswerId, CommentId = b.BestAnswer.CommentId }
Its type is Expression<Func<QABudle, QABundleWithCommentDto>> so if you write:
Expression<Func<QABudle, QABundleWithCommentDto>> selector = b => new
{
//rest of the code
}
now you can use selector like this: .Select(selector)

Grouping Linq Issue, can't get it right

public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public List<string> Email { get; set; }
}
I fetch data from database and put it in a list
List<Emp> employees= new List<Emp>();
// fill the list here via DB call
The list would have, please also note that Type field would always be same for same user but email would be different
employees[0] = new Emp{ EmpId = 1, Type = "User", Email = "one#test.com" };
employees[1] = new Emp{ EmpId = 1, Type= "User", Email = "two#test.com" };
employees[2] = new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com" };
employees[3] = new Emp{ EmpId = 2, Type= "Test", Email = "four#test.com"};
employees[4] = new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com" };
employees[5] = new Emp{ EmpId = 3, Type= "Test", Email = "six#test.com"};
employees[6] = new Emp{ EmpId = 4, Type= "User", Email = "seven#test.com"};
I'm trying to group Emp based on their EmpId
so the result should be a new list
Expected Result
Result = new Emp{ EmpId = 1, Type = "User", Email = "one#test.com", "two#test.com" };
new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com", "four#test.com" };
new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com", "six#test.com" };
new Emp{ EmpId = 4, Type = "User", Email = ""seven#test.com" };
//This is what I have done so far
// Please let me know if this is incorrect
var result = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into g
select new { Key = g.Key, Type = g.Key.Type, Emails = g.ToList() };
// My problem comes here when I loop this result
foreach (var r in result)
{
Console.WriteLine(r.Key.EmpId + "--" + r.Key.Type);
//This is where I need to get all emails of the Employee which I grouped
// iF I IMPLEMENT FOREACH
foreach (var e in r.Emails)
{
//?? WHAT i DO HERE
//e.?? to get email
}
// OR iF I IMPLEMENT FOR LOOP
for(int i = 0 ; i< r.Emails.Count; i++)
{
Console.WriteLine("Inner Loop" + "--" + r.Key.EmpId + "--" + r.Key.Type + "--" + r.Emails[0].ToString()); // r.Emails[0].ToString() prints out System.Collections.Generic.List '1[System.String]
}
}
Please let me know if I mad eany mistake or there's other way to do this.
All I need is Group employees based on EmpID and also have their Type but grouped Emails.
Your group emp.Email by new { emp.EmpId, emp.Type } means that each element of the group will have a key of the anonymous type, and an "element type" of List<string>. You're then propagating that element type using Emails = g.ToList() in your select clause. Therefore I'd expect the type of r.Emails to be List<List<string>> (which you should be able to validate in Visual Studio by hovering over r.Emails.
You could handle that in your loop - or you could just flatten it in your select call, creating a new Emp:
select new Emp {
EmpId = g.Key.EmpId,
Type = g.Key.Type,
Emails = g.SelectMany(x => x).ToList()
};
Here the SelectMany call is just flattening the "sequence of lists" to a single sequence.
Maybe a slight change could be usefull: if you change the Email property from a list to string you could group the employees like that:
// Group by EmpId
var group = employees.GroupBy(e => e.EmpId);
and get the list for a single emp like this:
// Example get email List of first emp
group.First().Select(g => g.Email);
You could change your Emp class so that EMail is a string instead of a List<string>.
The foreach loop then becomes
foreach(string e in r.EMails){
//e holds the EMail
//do stuff
}
Try This:-
var query1 = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into empgroup
select new
{
UserId = empgroup.Key.EmpId,
EmployeeType = empgroup.Key.Type,
EmaiIds = empgroup.SelectMany(x => x)
};
foreach (var x in query1)
{
Console.WriteLine(x.UserId);
Console.WriteLine(x.EmployeeType);
foreach (var emails in x.EmaiIds)
{
Console.WriteLine(emails);
}
}
void Main()
{
List<Emp> employees= new List<Emp>();
employees.Add(new Emp{ EmpId = 1, Type = "User", Email = "one#test.com" });
employees.Add(new Emp{ EmpId = 1, Type = "User", Email = "two#test.com" });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com" });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Email = "four#test.com" });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com" });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Email = "six#test.com" });
employees.Add(new Emp{ EmpId = 4, Type = "User", Email = "seven#test.com" });
var groupedList = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into g
select new { Key = g.Key, Type = g.Key.Type, Emails = g.ToList() };
foreach (var result in groupedList)
{
//I'm using LINQPad to output the results
result.Key.EmpId.Dump();
foreach(var email in result.Emails)
{
email.Dump();
}
}
}
public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public string Email { get; set; }
}
My results are:
or...
void Main()
{
List<Emp> employees= new List<Emp>();
employees.Add(new Emp{ EmpId = 1, Type = "User", Emails = new List<string>(){"one#test.com"} });
employees.Add(new Emp{ EmpId = 1, Type = "User", Emails = new List<string>(){"two#test.com"} });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Emails = new List<string>(){"three#test.com"} });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Emails = new List<string>(){"four#test.com"} });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Emails = new List<string>(){"five#test.com"} });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Emails = new List<string>(){"six#test.com"} });
employees.Add(new Emp{ EmpId = 4, Type = "User", Emails = new List<string>(){"seven#test.com"} });
var groupedList = from emp in employees
group emp.Emails by new { emp.EmpId, emp.Type } into g
select new Emp {
EmpId = g.Key.EmpId,
Type = g.Key.Type,
Emails = g.SelectMany(x => x).ToList()
};
foreach (var result in groupedList)
{ //I'm using LINQPad to output
result.EmpId.Dump();
result.Emails.ForEach(e => e.Dump());
}
}
public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public List<string> Emails { get; set; }
}
My results are also:

c# Listitems dont add if exisit in array

I have an array of days (mon, tue, etc..) that I might not want to show, so when I create a list of days, if they are already in the "hiddendays", it doesn't add them.
// This would return for example 1, 2
var hDays = account.ScheduleHiddenDays.Split(',').Select(int.Parse).ToList();
var daySunday = new ViewModels.Day()
{
Id = 0,
Name = "Sunday"
};
var dayMonday = new ViewModels.Day()
{
Id = 1,
Name = "Monday"
};
var dayTuesday = new ViewModels.Day()
{
Id = 2,
Name = "Tueday"
};
var dayWednesday = new ViewModels.Day()
{
Id = 3,
Name = "Wednesday"
};
var dayThursday = new ViewModels.Day()
{
Id = 4,
Name = "Thursday"
};
var dayFriday = new ViewModels.Day()
{
Id = 5,
Name = "Friday"
};
var daySaturday = new ViewModels.Day()
{
Id = 6,
Name = "Saturday"
};
// This is where I need to check if they exist in hDays, it doesn't add them to this list. But how?
model.ScheduleHiddenDays = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
Something along the lines of this:
var days = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
model.ScheduleHiddenDays = days.Where(x => !hDays.Contains(x.Id)).ToList();

Categories