实体框架调整

时间:2013-01-26 02:41:23

标签: entity-framework c#-4.0 entity-framework-mapping

遇到问题并希望有人可以提供帮助。

这是我的真实世界的例子。我有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个表)所以我不认为这应该是一个很大的问题,虽然我确定通过不做正确的事情来解决这个问题

2 个答案:

答案 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

我希望这会对你有所帮助。