Linq group result to list of object - c#

I'm trying group a collection of data by it's State but I'm stuck on the correct way to do this:
FileStateInfoDto
public class FileStateInfoDto : EntityDto<int>
{
public string StateName { get; set; }
public int StateNumber { get; set; }
public int FilesByStateCount { get; set; }
}
FileGroupDto
public class FileGroupDto : EntityDto<int>
{
public int CaseId { get; set; }
public string Name { get; set; }
public string ResourceKey { get; set; }
public bool IsFolder { get; set; }
public int SequenceNumber { get; set; }
public IList<FileStateInfoDto> FileStateInfo { get; set; }
public IList<FileGroupDto> FileGroups { get; set; }
public IList<FileInfoDto> Files { get; set; }
}
Here is the code I have:
return await Context.FileGroups
.Include(g => g.Case).Include(g => g.FileGroups).Include(g => g.Files)
.Where(g => g.Id == fileGroupId &&
g.CaseId == caseId &&
g.Case.CaseState != CaseState.Approved &&
g.Case.CaseState != CaseState.Submitted &&
(g.Case.CaseState != CaseState.Draft || g.Case.CreatorUserId == userId))
.OrderBy(g => g.SequenceNumber)
.Select(g => new FileGroup
{
Id = g.Id,
CaseId = g.CaseId,
Name = g.Name,
ResourceKey = g.ResourceKey,
IsFolder = g.IsFolder,
SequenceNumber = g.SequenceNumber,
FileGroups = g.FileGroups,
FileStateInfo = g.Files.GroupBy(f => f.State), <-- My problem
Files = g.Files.Where(f => f.IsActive && f.State != FileApprovalState.Approved).Select(
f => new File
{
Id = f.Id,
CreationTime = f.CreationTime,
CreatorUserId = f.CreatorUserId,
Title = f.Title,
FileName = f.FileName,
URL = f.URL,
Size = f.Size,
KeepOnPortal = f.KeepOnPortal,
CreatorUserName = Context.Users.FirstOrDefault(u => u.Id == (f.CreatorUserId ?? 0)).UserName,
CreatorUserRole = Context.CasePersons.Where(p => p.CaseId == caseId && p.UserId == f.CreatorUserId).Take(1).Select(p => p.CaseRoleType.Title).FirstOrDefault()
}
).ToList()
}).FirstOrDefaultAsync();
I'm trying to figure out how I should write this line FileStateInfo = g.Files.GroupBy(f => f.State) so it will give the expected result as below.
FileStateInfo = [{"StateName":"Approved","StateNumber":1, "FilesByStateCount":22},
{"StateName":"NotApproved","StateNumber":2, "FilesByStateCount":11}]
The State in g.Files.GroupBy(f => f.State) is an enum that contains Approved and NotApproved
StateName = Name of the State.
StateNumber = The Integer assinged.
FilesByStateCount = The files count by this state.
I hope it's possible because I've been trying to make this for a few days now.
I've tried things like this Post

Related

ViewModel with mixed fields and lists

I have the following ViewModel:
public class DayTaskListViewModel
{
public int Id { get; set; }
public string DateFormatted { get; set; }
public bool HasRegistrations { get; set; }
public bool HasStartedRegistrations { get; set; }
public string ItemName { get; set; }
public string WorkTypeName { get; set; }
public string Description { get; set; }
public string LocationName { get; set; }
public bool IsActive { get; set; }
public string UserName { get; set; }
public string StateStatus { get; set; }
public DateTime TodaysDate { get; set; }
public int WeekNumber { get; set; }
public int YearNumber { get; set; }
public string Msg { get; set; }
public string SignInUserName { get; set; }
public string UnitCode { get; set; }
public IEnumerable<Machinery> machineryList { get; set; }
public IEnumerable<Cleaning> cleaningList { get; set; }
}
In my controller I have this definition of the model to be sent to the view:
var model = (from a in _db.WorkTask.Where(y => y.TaskDate.Date == querytodaysDate.Date && y.IsActive == true && (y.IsPrivateUserName == null || y.IsPrivateUserName == currUserName))
join b in _db.WorkTaskLog.Where(x => (x.UserName == currUserName || x.UserName == null) && x.IsActive == true && x.StateStatusId < 4) on a.Id equals b.WorkTaskId into joinedT
from c in joinedT.DefaultIfEmpty()
select new DayTaskListViewModel
{
Id = a.Id,
DateFormatted = a.DateFormatted,
HasRegistrations = a.HasRegistrations,
HasStartedRegistrations = a.HasStartedRegistrations,
ItemName = a.ItemName,
WorkTypeName = a.WorkTypeName,
Description = a.Description,
IsActive = c.IsActive ? c.IsActive : false,
UserName = c.UserName ?? String.Empty,
StateStatus = c.StateStatus ?? "Klar",
WeekNumber = (int)currWeekNo,
YearNumber = (int)currYearNo,
Msg = "",
TodaysDate = (DateTime)todaysDate,
SignInUserName = currUserName,
LocationName = a.LocationName,
UnitCode = a.UnitCode,
//machineryList = _db.Machinery.ToList(),
//cleaningList = _db.Cleaning.ToList(),
}).ToList();
My problem is the following lines in the definition:
//machineryList = _db.Machinery.ToList(),
//cleaningList = _db.Cleaning.ToList(),
Everything works as expected, but as soon as I enable those 2 lines it breaks with null errors.
VS can compile, but it breaks runtime.
I think I see the problem, but I don't know how to solve it.
I want ALL fields in the ViewModel EXCEPT the 2 mentioned lines to be a list, and then the 2 lines to be separate lists independent of the majority.
I have tried all combinations of moving those lines around, but then VS complains.
An example from another controller is this:
DriveListViewModel model = new DriveListViewModel()
{
Drive = await _db.Drive
.Where(m => m.StatusId == 5 || m.StatusId == 1010 || m.StatusId == 1012)
.Where(m => m.LoadingComplete == null)
.Where(m => !m.UnitCode.Contains(excludeString))
.Include(s => s.DriveStatus)
.Include(d => d.Location)
.Include(f => f.Item)
.GroupBy(m => m.RegistrationNumber)
.Select(m => m.FirstOrDefault())
.OrderBy(m => m.DriverToLoad)
.ToListAsync(),
machineryList = await _db.Machinery.ToListAsync(),
cleaningList = await _db.Cleaning.ToListAsync(),
};
This works perfectly, but the former model definition as more complex, so basically, I need something similar to the latter example separating the 2 lists from the other properties in the ViewModel.
Maybe this is VERY simple - however I'm struggling with it...
Anyone see the solution to this?
I don't think that you model is a list with so many includes.
I guess you really need this ViewModel
public class ViewModel
{
public List<DayTaskListViewModel> DayTaskListViewModelList {get; set;}
public List<Machinery> MachineryList {get; set;}
public List<Cleaning> CleaningList {get; set;}
}
code
var dayTaskListViewModel= (from ....
.....
select new DayTaskListViewModel
{
Id = a.Id,
.......
}).ToList(); // or ToListAsync too?
var model = new ViewModel
{
DayTaskListViewModel = dayTaskListViewModel,
MachineryList = _db.Machinery.ToList(),
CleaningList = _db.Cleaning.ToList()
}
// or if you can or prefer , use async
MachineryList = await _db.Machinery.ToListAsync(),
CleaningList = await _db.Cleaning.ToListAsync(),
Here is a snip of the view:
Top:
#model List<Day.Models.ViewModels.DayTaskListViewModel>
#using Day.Extensions
Looping through all properties:
if (Model.Count > 0)
{
foreach (var item in Model)
{
<input name="description" class="form-input" id="description" type="text" value="#item.Description">
..Several input fields...
}
}
Works fine.
Then I need to include select fields using the machineryList from the ViewModel:
<select name="machinery" asp-items="#Model.machineryList.ToSelectListItem((int)defaultMachinery)"></select>

To find the best Projects depending on the Project Likes, Project Connected and Project Rating

I have this table:
PL_ProjectLikes
PC_ProjectConnect
PR_ProjectRating
P_Project
PL_PageLayout
This is my link query:
List<PProject> p = ctx.PProject.Where(x => x.PCountryCode == cC && x.PParentalGuidence == r).ToList();
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
Now PL_PageLayout has a field called PL_P_Id or PlPId, this is a guid.
What i want is to take theses tables figure out a rating or sum or count to pull the best projects to be filtered at the top of the list.
What i have done to extract each of these tables by grouping them with the PIdG which is a guid and is liked to each of the tables from the project and each project is a PL_PageLayout.
Extracted values from the tables:
PL_ProjectLIke:
var plike = ctx.PlProjectLike.Where(x => x.PlValue == "Like").Select(c => c).GroupBy(g => new { g.PlPIdG }, (key, group) => new { sumR = group.Count(), pidG = key.PlPIdG });
List<string> p0p = plike.Select(t => t.pidG).ToList();
PR_ProjectRating:
var prating = ctx.PrProjectRating.Where(x => x.PrIsDeleted == false).Select(k => k).GroupBy(g => new { g.PrPIdG }, (key, group) => new { sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG });
List<string> p0 = prating.Select(t => t.pidG).ToList();
PC_ProjectConnect:
var pconnect = ctx.PcProjectConnect.Where(x => x.PcStatus == "Connected").Select(c => c).GroupBy(g => new { g.PcPIdG }, (key, group) => new { sumR = group.Count(), pidG = key.PcPIdG });
List<string> p0pp = pconnect.Select(t => t.pidG).ToList();
How do i combine these filters above to find the best projects or pagelayouts using linq?
I tried this:
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
Which works and gets the best projects by the sum of the ratings for each project, but how do i combine the other two querys to find the best project?
Would this be the answer or would this just get the query of the last set:
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0p.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0pp.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
Every time im liking a project as im testing its pushing the project down the list so that bit of code above is not working but making some progress
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = pppp.OrderBy(c => p0.Contains(c.PlPId) ? p0.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0p.Contains(c.PlPId) ? p0p.IndexOf(c.PlPId) : int.MaxValue).ToList();
pppp = pppp.OrderBy(c => p0pp.Contains(c.PlPId) ? **p0pp**.IndexOf(c.PlPId) : int.MaxValue).ToList();
I have put some test code together at RexTester but I am not sure of your question. I think you can just order the result lists as they are created, or am I just misunderstanding the question
public class PlProjectLike
{
public int PlId { get; set; }
public Guid PlPIdG { get; set; }
public int PlUId { get; set; }
public string PlValue { get; set; }
public DateTime PlCreatedDate { get; set; }
}
public class PcProjectConnect
{
public int PcId { get; set; }
public Guid PcPIdG { get; set; }
public int PcUId { get; set; }
public DateTime PcCreatedDate { get; set; }
public string PcStatus{ get; set; }
}
public class PrProjectRating
{
public int PrId { get; set; }
public int PrUId { get; set; }
public string PrText { get; set; }
public int PrValue { get; set; }
public Guid PrPIdG { get; set; }
public DateTime PrCreatedDate { get; set; }
public bool PrIsDeleted{ get; set; }
}
public class PProject
{
public int PId { get; set; }
public Guid PIdG { get; set; }
public string PName { get; set; }
public DateTime PDateCreated { get; set; }
public bool PDeleted { get; set; }
public int PUId { get; set; }
public int PTtId { get; set; }
public string PCountry { get; set; }
public string PCountryCode { get; set; }
public string PParentalGuidence { get; set; }
public string PConnectionType { get; set; }
}
public class PlPageLayout
{
public int PLId { get; set; }
public Guid PlPId { get; set; }
public string PLName { get; set; }
}
public class CTX
{
public List<PProject> PProject { get; set; }
public List<PlPageLayout> PlPageLayout { get; set; }
public List<PlProjectLike> PlProjectLike { get; set; }
public List<PrProjectRating> PrProjectRating { get; set; }
public List<PcProjectConnect> PcProjectConnect { get; set; }
public CTX()
{
PProject = new List<PProject>();
PlPageLayout = new List<PlPageLayout>();
PlProjectLike = new List<PlProjectLike>();
PrProjectRating = new List<PrProjectRating>();
PcProjectConnect = new List<PcProjectConnect>();
}
}
public class LikeGroup
{
public int sumR { get; set; }
public Guid pidG { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
CTX ctx = new CTX();
String r = "R";
string cC = "us";
// Select project for country and rating
List<PProject> p = ctx.PProject.Where(x => x.PCountryCode == cC && x.PParentalGuidence == r).ToList();
// List of PlPageLayouts where the PlPId is in the selected PProject list
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
// List of Count/PlPIdG from PlProjectLike where the PlValue is 'Like' Ordered by the count descending
List<LikeGroup> plike = ctx.PlProjectLike.Where(x => x.PlValue == "Like").Select(c => c).GroupBy(g => new { g.PlPIdG }, (key, group) => new LikeGroup() { sumR = group.Count(), pidG = key.PlPIdG }).OrderByDescending(dat => dat.sumR).ToList();
// List of Sum(PrValue)/PlPIdG from PrProjectRating where PrIsDeleted is false Ordered by the Sum(PrValue) descending
List<LikeGroup> prating = ctx.PrProjectRating.Where(x => x.PrIsDeleted == false).Select(k => k).GroupBy(g => new { g.PrPIdG }, (key, group) => new LikeGroup(){ sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG }).OrderByDescending(dat => dat.sumR).ToList();
// List of Count/PlPIdG from PcProjectConnect where PcStatus is Connected Ordered by the count descending
List<LikeGroup> pconnect = ctx.PcProjectConnect.Where(x => x.PcStatus == "Connected").Select(c => c).GroupBy(g => new { g.PcPIdG }, (key, group) => new LikeGroup() { sumR = group.Count(), pidG = key.PcPIdG }).OrderByDescending(dat => dat.sumR).ToList();
List<PlProjectLike> OrderedProjectLikeList =
(from pl in ctx.PlProjectLike
join ord in plike on pl.PlPIdG equals ord.pidG
orderby ord.sumR descending
select pl).ToList();
List<PrProjectRating> OrderedPrProjectRatingList =
(from pr in ctx.PrProjectRating
join ord in prating on pr.PrPIdG equals ord.pidG
orderby ord.sumR descending
select pr).ToList();
List<PcProjectConnect> OrderedPcProjectConnectList =
(from pc in ctx.PcProjectConnect
join ord in prating on pc.PcPIdG equals ord.pidG
orderby ord.sumR descending
select pc).ToList();
}
}
From the help of this answer:
https://stackoverflow.com/questions/65014531/summing-a-value-inside-of-a-anonymous-type
I added the following code to get the best projects:
var ratings =
from r1 in ctx.PrProjectRating
where r1.PrIsDeleted == false
group r1.PrValue by r1.PrPIdG into g
select new
{
Id = g.Key,
Sum = g.Sum(),
};
var likes =
from l in ctx.PlProjectLike
where l.PlValue == "Like"
group 1 by l.PlPIdG into g
select new
{
Id = g.Key,
Count = g.Count(),
};
var connects =
from c1 in ctx.PcProjectConnect
where c1.PcStatus == "Connected"
group 1 by c1.PcPIdG into g
select new
{
Id = g.Key,
Count = g.Count(),
};
var ids = ratings.Select(r => r.Id)
.Union(likes.Select(l => l.Id))
.Union(connects.Select(c => c.Id))
.ToHashSet();
var query =
from i in ids
join ra in ratings on i equals ra.Id into rs
from ra in rs.DefaultIfEmpty()
join l in likes on i equals l.Id into ls
from l in ls.DefaultIfEmpty()
join co in connects on i equals co.Id into cs
from co in cs.DefaultIfEmpty()
select new
{
Id = i,
Ratings = ra?.Sum ?? 0,
Likes = l?.Count ?? 0,
Connects = co?.Count ?? 0,
};
List<PlPageLayout> pppp = ctx.PlPageLayout.Where(x => p.Select(n => n.PIdG).Contains(x.PlPId)).ToList();
pppp = query.OrderByDescending(x => x.Ratings + x.Likes + x.Connects).SelectMany(j => pppp.Where(s => s.PlPId == j.Id)).ToList();

Select single object and it's corresponding list

I have a class which contains ProjectID and its detail as follows and I would like to retrieve the list detail from the SQL server. I am struggling to convert list of rows into ProjectModel.
I have tried below and referred various source but no luck. I want to write code for get list instead of BuildAutoCompleteList(PTO).
Should i need to use groupby to achieve the result.
Class
public class ProjectModel
{
public string ProjectName { get; set; }
public Guid ProjectID { get; set; }
public IEnumerable<SegmentModel> Segments { get; set; }
}
public class SegmentModel
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string MileStone { get; set; }
}
public class ProjectMilestone
{
public string ProjectName { get; set; }
public Guid ProjectID { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string MileStone { get; set; }
public ProjectMilestone() { }
}
Entity
var collection = _db.GetReportMilestones().Join(_db.GetReports(), RM => RM.ReportId, R => R.Id,
(RM, R) => new { RM, R }).
Join(_db.GetProjects(), P => P.R.ProjectId, PR => PR.Id, (P, PR) => new { P, PR }).Where(M => M.P.R.StateId == 1)
.Select(PTO => new ProjectTimelineModel
{
ProjectName = PTO.PR.Name,
ProjectID = PTO.PR.Id,
Segments = BuildAutoCompleteList(PTO)
}).ToList();
Below is my attempt, which throws the error.
var collection = _db.GetReportMilestones().Join(_db.GetReports(), RM => RM.ReportId, R => R.Id,
(RM, R) => new { RM, R }).
Join(_db.GetProjects(), P => P.R.ProjectId, PR => PR.Id, (P, PR) => new { P, PR }).Where(M => M.P.R.StateId == 1)
.Select(PTO => new ProjectMilestone
{
ProjectName = PTO.PR.Name,
ProjectID = PTO.PR.Id,
StartDate = PTO.P.RM.ScheduledDate,
EndDate = PTO.P.RM.PassedDate,
MileStone = PTO.P.RM.Name
}).ToList();
var results = collection.OrderBy(n => n.ProjectName);
var groupbyResult = results.GroupBy(n => new { n.ProjectID, n.ProjectName }).Select(x => new ProjectTimelineModel()
{
ProjectID = x.Key.ProjectID,
ProjectName = x.Key.ProjectName,
Segments = x.GroupBy(n => n.ProjectID)
}).ToList();

Find Unique count on field using LINQ

I am trying to determine the Distinct count for a particular field in a collection of objects.
private static RemittanceCenterBatchSummaryListModel SummarizeFields(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
{
var result = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new{x.FileId, x.SourceFileName, x.BatchCode, x.BatchType})
.Select(x => new RemittanceCenterBatchSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
BatchCode = x.Key.BatchCode,
BatchType = x.Key.BatchType,
DetailRecordCountAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Adc),
DetailRecordCountNotAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Exd),
AmountAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Adc).Sum(y => y.PaymentAmount),
AmountNotAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Exd).Sum(y => y.PaymentAmount),
UniqueFileCount = x.Select(y => x.Key.FileId).Distinct().Count()
});
return CreateSummaryListModel(result);
}
Input entities:
public class RemittanceCenterSummaryListModel
{
public RemittanceCenterSummaryListModel()
{
this.RemittanceBatchSummaryRecord = new List<RemittanceBatchProcessingModel>();
}
public List<RemittanceBatchProcessingModel> RemittanceBatchSummaryRecord { get; private set; }
}
public class RemittanceCenterBatchSummarizedModel
{
public string FileId { get; set; }
public string SourceFileName { get; set; }
public string BatchCode { get; set; }
public string BatchType { get; set; }
public int DetailRecordCountAdc { get; set; }
public int DetailRecordCountNotAdc { get; set; }
public int DetailRecordCountTotal { get; set; }
public decimal AmountAdc { get; set; }
public decimal AmountNotAdc { get; set; }
public decimal AmountTotal { get; set; }
public BillingSystemCode BillingSystemCode { get; set; }
public int UniqueFileCount { get; set; }
}
private static RemittanceCenterBatchSummaryListModel CreateSummaryListModel(IEnumerable<RemittanceCenterBatchSummarizedModel> summaryModels)
{
var summaryModelList = new RemittanceCenterBatchSummaryListModel();
foreach (var summaryRec in summaryModels)
{
var summaryModel = new RemittanceCenterBatchSummarizedModel
{
FileId = summaryRec.FileId,
SourceFileName = summaryRec.SourceFileName,
BatchCode = summaryRec.BatchCode,
BatchType = summaryRec.BatchType,
DetailRecordCountAdc = summaryRec.DetailRecordCountAdc,
DetailRecordCountNotAdc = summaryRec.DetailRecordCountNotAdc,
AmountAdc = summaryRec.AmountAdc,
AmountNotAdc = summaryRec.AmountNotAdc,
UniqueFileCount = summaryRec.UniqueFileCount
};
summaryModelList.RemittanceBatchSummary.Add(summaryModel);
}
return summaryModelList;
}
Example input records:
Record1:
FileId: '123'
SourceFileName: 'test.file.txt'
BatchCode: 'aaa'
BatchType: 'scanned'
PaymentAmount: '50.00'
BillingSystemCode: 'Adc'
Record1:
FileId: '1234'
SourceFileName: 'test.file2.txt'
BatchCode: 'aab'
BatchType: 'scanned'
PaymentAmount: '52.00'
BillingSystemCode: 'Adc'
ActualOuput for UniqueFileCount Field:
UniqueFileCount = 1
ExpectedOutput results for UniqueFileCount Field:
UniqueFileCount = 2
What am I doing wrong?
It sounds like you want the distinct count of FileId for the entire collection and not just for each group, which will always be 1 since FileId is one of the fields you group on. If that is the case then you can just calculate that count first
int distinctFileIds = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecor‌​d
.Select(x => x.FileId)
.Distinct()
.Count();
Then use that in your Linq query
UniqueFileCount = distinctFileIds

How to flatten collection using SelectMany

I have the following entities (I18N is a localized entity):
public class Post {
public Int32 Id { get; set; }
public Boolean IsPublished { get; set; }
public List<PostI18N> PostsI18N { get; set; }
public List<Tag> Tags { get; set; }
public Author { get; set; }
}
public class Tag {
public List<TagI18N> TagsI18N { get; set; }
}
public class Author {
public Int32 Id { get; set; }
public String Name { get; set; }
}
public class PostI18N {
public Int32 Id { get; set; }
public String Text { get; set; }
public String Title { get; set; }
}
public class TagI18N {
public Int32 Id { get; set; }
public String Name { get; set; }
}
I need to get all information of 4 posts so I tried to flatten the query:
var posts = await _context
.Posts
.SelectMany(x => x.PostsI18N, (Post, PostI18N) =>
new { Post, PostI18N, Post.Tags, Post.Author })
.Where(x => x.PostI18N.Language == "en")
.Select(x => new PostDTO {
Id = x.Post.Id,
Title = x.PostI18N.Title,
Text = x.PostI18N.Text,
AuthorName = x.Author.Name
TagsNames = // Names taken from x.Tags.TagsI18N where TagsI18N
// language is "en" ... So, for each tag look the
// one Tag.TagI18N which Tag.TagI18N.Language = "en"
// and get Tag.TagI18N.Name
})
.Take(4)
.ToListAsync();
PROBLEM:
The problem is that I also need the TagsI18N flatten so I can take their names for English language ...
It this possible with SelectMany? How should I do this?
Try it in query syntax instead:
var posts = await (
from p in _context.Posts
from pn in p.PostsI18N
where pn.Language == "en"
select new PostDTO {
Id = p.Id,
Title = pn.Title,
Text = pn.Text,
AuthorName = p.Author.Name,
TagsNames = from t in p.Tags
from tn in t.TagsI18N
where tn.Language == "en"
select tn.Name
}).Take(4).ToListAsync();
The SelectMany syntax should work as well, but it gets a bit "nested":
var posts = await _context
.Posts
.SelectMany(x => x.PostsI18N, (Post, PostI18N) =>
new { Post, PostI18N, Post.Tags, Post.Author })
.Where(x => x.PostI18N.Language == "en")
.Select(x => new PostDTO {
Id = x.Post.Id,
Title = x.PostI18N.Title,
Text = x.PostI18N.Text,
AuthorName = x.Author.Name
TagsNames =
x.Tags.SelectMany(t => t.TagsI18N, (Tag, TagI18N) =>
new { Tag, TagI18N })
.Where(t => t.TagI18N.Language == "en")
.Select(t => t.TagI18N.Name)
})
.Take(4)
.ToListAsync();

Categories