遇到问题并希望有人可以提供帮助。
这是我的真实世界的例子。我有4张桌子:
人
计划
覆盖范围和
CoveredMembers
每个人都可以有很多计划,每个计划都可以有很多计划。每个覆盖范围都可以有很多CoveredMembers。
我需要一个将在Plan.PlanType == 1和CoveredMembers.TermDate == null上应用过滤器的查询。此查询应该带回任何未终止医疗类型计划的人。但我也需要包括所有儿童记录。适合过滤器的每个人的计划,覆盖范围和覆盖成员。
这个SQL语句就是这样做的:
SELECT Person.*, Plans.*, Coverages.*, CoveredMembers.*
FROM Person P
INNER JOIN Plan PL ON P.PersonID = PL.PersonID
INNER JOIN Coverage C on PL.PlanID = C.PlanID
INNER JOIN CoveredMember CM on C.CoverageID = CM.CoverageID
WHERE CM.TermDate = NULL AND PL.PlanType = 1
EF中的(4.0 vs 2010)我已经完成了这个
var Q from p in context.Persons
join pp in context.Plans
on p.PersonID equals pp.PersonD
join c in context.Coverages
on pp.PlanID equals c.PlanID
join cm in context.CoveredMember
on c.CoverageID equals cm.CoverageID
where cm.TermDate == null && pp.PlanType = 1 &&
pp.ActiveFlag == true
select p;
然后
var people = Q.Include(people =>
people.Plans.Select(plans => plans.Coverages.Select(cc => cc.CoveragedMembers)))
.ToList ();
如果我在var people = Q行设置断点并执行
((System.Data.Objects.ObjectQuery)Q).ToTraceString();
在使用ToList()实际将查询发送到数据库之前(在include语句之前) 我接受了这个查询并找回了我应该回来的确切记录数量。
然后我运行sql跟踪(在SQL事件探查器中)并将查询发送到数据库(包含语句)。我看到发送到数据库的sql语句已经丢失了所有的过滤功能。 它基本上返回了相同的人,但子对象上的过滤器已经消失了 正在返回这些人的所有数据。 (plan.PlanType = 1且coveredMember.TermDate = null缺失)
也许这不是实现这个目标的方法?有人有什么想法?甚至可以使用EF吗? 这是一个非常简单的SQL语句(尽管跨越4个表)所以我不认为这应该是一个很大的问题,虽然我确定通过不做正确的事情来解决这个问题
答案 0 :(得分:1)
我认为这是Include
的位置。将Include
直接放在它们适用的实体后面或多或少是常见的。我会告诉你我的意思,同时使用导航属性重写你的查询:
var q = from p in context.Persons
.Include(people => people.Plans
.Select(plans => plans.Coverages
.Select(cc => cc.CoveragedMembers)))
from pp in p.Plans
from c in pp.Coverages
from cm in c.CoveragedMembers
where cm.TermDate == null && pp.PlanType = 1 && pp.ActiveFlag
select p;
(使用导航属性本质上不会改变任何东西,但它会让生活变得更轻松)。我已经看到在linq语句末尾放置的包含被解释为外连接,但同样包括在开始到内连接的权利。
我可以补充一点,如果可以预先确定您需要哪些数据,并且将它们(Include
)项目(select
)转换为(命名或匿名)类型,则根本不需要select new { Person = p, Plan = pp, CoveredMember = cm }
s ,例如
select p
代替select new { Person = p.Name, Plan = pp.Plan, CoveredMember = cm.Name }
。更好的是,选择具体的属性:
Includes
您将大大减少获取的数据量。 {{1}}有一种方法可以在宽度和长度上查询查询结果。
答案 1 :(得分:0)
你cannot use filtering with Eager loading (Include)
。
所以你可以做类似下面的事情(这是一个示例代码)
public Company Get(int id)
{
var query = from c in
(from co in db.Companies
where co.Id == id
select new
{
Company = co,
CompanyPerson = from person in co.Persons
where person.IsActive && !person.IsDeleted
select person
})
select c;
//Create my company object
Company company = new Company();
foreach (var item in query)
{
company = item.Company;
//Add persons to my company object
foreach (var companyPerson in item.CompanyPerson)
{
company.Persons.Add(companyPerson);
}
}
return company;
}
有关详细信息,请查看此帖子Eager Loading (include) with filter in Entity Framework
我希望这会对你有所帮助。