Entity framework 实体框架调整

Entity framework 实体框架调整,entity-framework,c#-4.0,entity-framework-mapping,Entity Framework,C# 4.0,Entity Framework Mapping,遇到问题,希望有人能帮助 这是我真实世界的例子。我有4张桌子: 人 计划 覆盖范围和 被覆成员 每个人都可以有很多计划,每个计划都可以有很多保险范围。每个覆盖范围都可以有多个覆盖成员 我需要一个将对Plan.PlanType==1和CoveredMembers.TermDate==null应用筛选器的查询。此查询将带回任何拥有未终止的医疗类型计划的人员。但我还需要包括所有的儿童记录。每一个将过滤器与他们的计划、覆盖范围和覆盖成员相匹配的人 此SQL语句将执行以下操作: SELECT Person

遇到问题,希望有人能帮助

这是我真实世界的例子。我有4张桌子:

计划
覆盖范围和 被覆成员

每个人都可以有很多计划,每个计划都可以有很多保险范围。每个覆盖范围都可以有多个覆盖成员

我需要一个将对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行上设置断点并执行

((System.Data.Objects.ObjectQuery)Q).ToTraceString();
在使用ToList()将查询实际发送到数据库之前(在include语句之前) 我接受了这个查询,得到了我应该得到的确切数量的记录

然后我运行一个sql跟踪(在sql Profiler中),并将查询发送到数据库(include语句)。我看到发送到数据库的sql语句丢失了所有筛选。 它基本上返回相同的人,但是子对象上的过滤器不见了 正在返回这些人的所有数据。(缺少plan.PlantType=1和coveredMember.TermDate=null)

也许这不是实现这一目标的方法?有人有什么想法吗?EF也有可能吗?
这是一个非常简单的SQL语句(虽然跨越了4个表),因此我认为这不应该是一个很大的问题,尽管我确信我的问题在于没有正确地执行某些操作

无法使用带即时加载(Include)
的筛选

因此,您可以执行以下操作(这是一个示例代码)

有关更多信息,请查看此帖子


我希望这将对您有所帮助。

我认为这是
包含的位置。将
Include
s直接放在它们所应用的实体后面,这或多或少是很常见的。我将向您展示我的意思,同时使用导航属性重写您的查询:

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;
select new { Person = p.Name, Plan = pp.Plan, CoveredMember = cm.Name }
(使用导航属性不会从本质上改变任何东西,但会使生活更轻松)。我见过放在linq语句末尾的include被解释为外部联接,但同样的include放在内部联接的开头

我可以补充一点,如果可以事先决定需要哪些数据,您根本不需要
Include
,并将这些数据投影到(命名或匿名)类型中,例如

select new { Person = p, Plan = pp, CoveredMember = cm }
不要选择
,而是选择p
。更好的方法是选择特定的属性:

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;
select new { Person = p.Name, Plan = pp.Plan, CoveredMember = cm.Name }

您将大大减少获取的数据量
Includes(代码>包含)
可以放大查询结果的宽度和长度。

您是否将
Q
Q
混在一起,或者它们不同?它们是相同的。那是个打字错误。编辑它。我知道可以在上下文中执行此操作。Persons.Include(“Plans.Coverages.CoveredMembers”).ToList();但是我需要在includedoesn中过滤那些属性,以实现我想要的。为了简单起见,我只深入了两个层次(个人和计划)。创建的sql是一个左外部联接,并返回所有人员,无论他们是否具有PlanType=1。仅批准计划类型1在计划列表中是拥有该计划的人员。但是,如果我的数据库中有500000K人,只有25K人有PlantType 1,那么它将带回475K条不需要的记录。看来这个左外连接是设计的?如果是这种情况,则EF延迟。这应该是一个简单的查询。也许我对EF的期望太高了,但这似乎是一件非常简单的事情,如果它做不到,那么在我看来它是完全无用的。我很惊讶创建这个避风港的开发人员想到了一种方法。@DexterMorgan是的,您提供的链接提供了很多关于这种情况的信息。您使用的是哪种EF版本?我在visual studio中安装并引用了4.1,但上面说的是4.0still@DexterMorgan现在微软发布了EF 6 Alpha 2。如果你运行Vs 2012,然后尝试完成您在ef 4.1中尝试的功能。因为有时他们提供了该功能(可能是)。查看此链接了解有关最新版本的更多详细信息这很好接受匿名属性为只读。这意味着你不能用它做任何事情接受阅读它,这没有太多帮助。当你需要一个实体而不是一个匿名类型时,有没有可能重新思考一下(例如,我经常对搜索结果使用这种方法,等等,然后当我想修改一个或专门使用它时,加载实体)?还有一些情况下,您必须在EF之外工作(即,如果先执行代码/数据库,则运行存储的过程)。我想知道你现在的一些挣扎是否不能通过你如何使用你的实体来解决。与第三方一起运行您的设计和方法可能会有所帮助。@dexterm您还可以创建命名类型,例如
selectnewpersondto{Person=p.Name,…}
。但是我很好奇,第一个查询现在包括了过滤器吗?@Matthew我很感激这个建议,但是我们每周都会收到一个文件来更新人员和信息。该文件包含16K人。即使只有25%的用户进行了4K的数据更改,也可以访问数据库。我宁愿马上把它们都拿回来,让它们可以写。另外,也许只有我一个人,但如果你只是想调用存储过程,我真的不认为有EF开销的意义。额外的开销应该可以减少编写存储过程的需要。这只是我的观点。开销是用来抽象您过去必须执行的DAO层活动,并在您现在如何将对象视为实体而不必太担心持久性方面提供一点范例转换。还有一些东西(和批量读取)/