Linq:使用三个嵌套级别进行查询
所以我有三张桌子:
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 )
这些是我的数据传输对象:
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 Systems { get; set; } } public class UserDTO { public int pkUserId { get; set; } public string Name { get; set; } public IEnumerable Companies { get; set; } }
这是我想要做的Linq查询:
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();
此查询的问题在于最内部的查询
from system in db.tblSystem where system.fkCompanyId==company.pkCompanyId select new SystemDTO() { pkSystemId=system.pkSystemID, Name=system.systemName, fkCompanyId=system.fkCompanyID }
导致linq将sql转换为每个实体一个选择。 我知道我可以跳过select并循环结果并设置属性。 像这样:
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(); } }
这将导致linq执行两个选择而不是每个实体一个。 所以现在回答我的问题。 有没有其他方法这样做? 我可以用另一种方式填充内部集合吗?
任何建议将不胜感激
编辑
建议是使用loadoption。 我找不到系统和公司之间的负载选项。 但我可以包括之间的loadoption。 公司和用户是这样的:
var option=new DataLoadOptions(); option.LoadWith(a=>a.fkCompanytblUsers); db.LoadOptions=option;
但这对查询没有影响,它仍然被翻译成许多选择
EDIT2
正如在答案评论中所述,加载选项不适用于此类linq查询。
好的,这是一个提议,您可以使用它来获取单个查询中的所有内容。 我将简化数据模型以用于演示目的:
select * from ParentTable join ChildLevel1 on ... join ChildLevel2 on ...
该查询将同时为您提供所有三个树级别。 这将是非常有效的。 但数据将是多余的。 您需要进行一些客户端处理以使其再次可用:
var parents = from x in queryResults group x by new { /* all parent columns here */ }) into g select new Parent() { ParentData = g.Key, Children1 = from x in g group x by new { /* all ChildLevel1 columns here */ }) into g select new Child1() { Child1Data = g.Key, Children2 = ... //repeat } }
您需要通过分组来删除冗余。 换句话说:查询已对数据进行非规范化,我们需要再次对其进行规范化。
这种方法非常麻烦但速度很快。
我自己搞清楚了。 我能看到的最好的方法就是这样做(但如果其他人有更好的建议请再加上):
var lsSystem= db.tblSystem.Select (s =>new SystemDTO() { pkSystemId=s.pkSystemID, Name=s.systemName, fkCompanyId=s.fkCompanyID } ).ToLookup (s =>s.fkCompanyId);
然后在linq查询中使用lsSystem,如下所示:
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=lsSystem[company.pkCompanyID] } ) } ).ToList();
这将导致两个选择语句一个用于系统,一个用于公司用户
您是否查看了LoadOptions
和更具体的LoadWith
。
这将阻止Linq2sql延迟加载并将进行急切加载。
这里有一个简单的例子: http : //davidhayden.com/blog/dave/archive/2007/08/05/LINQToSQLLazyLoadingPropertiesSpecifyingPreFetchWhenNeededPerformance.aspx
上述就是C#学习教程:Linq:使用三个嵌套级别进行查询分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/954863.html