So, I have three tables:
CREATE TABLE tblUser ( [pkUserID] [int] IDENTITY(1,1) NOT NULL, [userName] [varchar](150) NULL, [fkCompanyID] [int] NOT NULL ) CREATE TABLE tblCompany ( [pkCompanyID] [int] IDENTITY(1,1) NOT NULL, [name] [varchar](255) NULL ) CREATE TABLE tblSystem ( [pkSystemID] [int] IDENTITY(1,1) NOT NULL, [systemName] [varchar](150) NULL, [fkCompanyID] [int] NULL )
These are my data transfer objects:
public class SystemDTO { public int pkSystemId { get; set; } public string Name { get; set; } public int? fkCompanyId { get; set; } } public class CompanyDTO { public int pkCompanyId { get; set; } public string Name { get; set; } public IEnumerable<SystemDTO> Systems { get; set; } } public class UserDTO { public int pkUserId { get; set; } public string Name { get; set; } public IEnumerable<CompanyDTO> Companies { get; set; } }
This is the Linq query I'm trying to do:
var result= ( from user in db.tblUsers select new UserDTO() { pkUserId=user.pkUserID, Name=user.realName, Companies= ( from company in db.tblCompanies where user.fkCompanyID==company.pkCompanyID select new CompanyDTO() { pkCompanyId=company.pkCompanyID, Name=company.name, Systems= ( from system in db.tblSystem where system.fkCompanyId==company.pkCompanyId select new SystemDTO() { pkSystemId=system.pkSystemID, Name=system.systemName, fkCompanyId=system.fkCompanyID } ) } ) } ).ToList();
The problem with this query is that the innermost query
from system in db.tblSystem where system.fkCompanyId==company.pkCompanyId select new SystemDTO() { pkSystemId=system.pkSystemID, Name=system.systemName, fkCompanyId=system.fkCompanyID }
forces linq to translate sql to one select per object. I know that I can skip the selection and encode the result and set the property. Like this:
var lsSystem= db.tblSystem.Select (s =>new SystemDTO(){pkSystemId=s.pkSystemID,Name=s.systemName,fkCompanyId=s.fkCompanyID}).ToList(); foreach (var user in result) { foreach (var company in user.Companies) { company.Systems=lsSystem.Where (a =>a.fkCompanyId==company.pkCompanyId).ToList(); } }
This will cause linq to make two choices, not a single object. So now to my questions. Is there any other way to do this? Can the internal collection be filled out differently?
Any suggestions would be appreciated.
EDIT
It was supposed to use loading. I can not find a download between the system and the company. But I can enable loadoption between. Company and user:
var option=new DataLoadOptions(); option.LoadWith<tblCompany>(a=>a.fkCompanytblUsers); db.LoadOptions=option;
But this does not affect the request, it still translates into many options
EDIT2
As stated in the answers to the answers, the boot options are not used for this kind of linq query.