4

我的表结构如下:

Person 1-M PesonAddress
Person 1-M PesonPhone
Person 1-M PesonEmail
Person 1-M Contract 
Contract M-M Program
Contract M-1 Organization

在此查询结束时,我需要一个填充的对象图,其中每个人都有他们的:

  • 个人地址
  • 个人电话的
  • PesonEmail的
  • 个人电话的
  • 合同的 - 这有其各自的
    • 程式

现在我有以下查询,我认为它工作得很好,但它有几个问题:

from people in ctx.People.Include("PersonAddress")
                        .Include("PersonLandline")
                        .Include("PersonMobile")
                        .Include("PersonEmail")
                        .Include("Contract")
                        .Include("Contract.Program")
where people.Contract.Any(
    contract => (param.OrganizationId == contract.OrganizationId)
        && contract.Program.Any(
            contractProgram => (param.ProgramId == contractProgram.ProgramId)))
select people;

问题在于它会根据标准过滤人员,而不是合同或合同的程序。它带回了所有合同,每个人不仅拥有 OrganizationId 为 x 的合同,而且每个合同的程序也同样如此。

我想要的只是那些至少有一个合同的组织 ID 为 x 的人,并且该合同有一个 ID 为 y 的程序......并且返回的对象图只有匹配的合同和该合同中匹配的程序。

我有点明白为什么它不工作,但我不知道如何改变它,所以它工作......

这是我迄今为止的尝试:

from people in ctx.People.Include("PersonAddress")
                        .Include("PersonLandline")
                        .Include("PersonMobile")
                        .Include("PersonEmail")
                        .Include("Contract")
                        .Include("Contract.Program")
let currentContracts = from contract in people.Contract
                where (param.OrganizationId == contract.OrganizationId)
                select contract 
let currentContractPrograms = from contractProgram in currentContracts 
                    let temp = from x in contractProgram.Program
                        where (param.ProgramId == contractProgram.ProgramId)
                        select x
                    where temp.Any()
                    select temp
where currentContracts.Any() && currentContractPrograms.Any()
select new Person { PersonId = people.PersonId, FirstName = people.FirstName, ..., ...., 
                    MiddleName = people.MiddleName, Surname = people.Surname, ..., ...., 
                    Gender = people.Gender, DateOfBirth = people.DateOfBirth, ..., ...., 
                    Contract = currentContracts, ... };  //This doesn't work

但这有几个问题(其中 Person 类型是 EF 对象):

  • 我只能自己做映射,在这种情况下,有很多东西要映射
  • 当我尝试将列表映射到属性(即奖学金 = currentScholarships)时,它说我不能因为IEnumerable试图被转换为EntityCollection
  • 包含不起作用

因此,我如何让它发挥作用。请记住,我正在尝试将其作为编译查询来执行,所以我认为这意味着匿名类型已被淘汰。

4

3 回答 3

2

只是不要使用包含,手动过滤。您可以先筛选与所需 ProgramId 和 OrganizationId 关联的合同。之后,您可以选择与所选合同关联的人员。A已附上示例代码。您需要对其进行修改以正确利用 MM 关系。但无论如何逻辑应该是正确的。

public class PersonDetails
{
    public Person person;
    public List<Contract> contracts;
}

var selected_program = (from pr in ctx.Programs where pr.Id == param.ProgramId select pr).Single();

//select contracts by OrganizationId and ProgramId
var selected_contracts = from c in ctx.Contracts
                where c.OrganizationId == param.OrganizationId
                from p in ctx.Programs
                where p.Id == param.ProgramId
                where p.ContractId == c.Id
                select c;

//select persons and contracts
var people =
    from p in ctx.People
    select new PersonDetails()
    {
        person = p,
        contracts = (from c in selected_contracts
                     where c.PersonId == p.Id
                     select c).ToList()
    };

//select people associated with selected contracts
var selected_people = from p in people where p.contracts.Count > 0 select p;
于 2010-05-03T11:41:05.667 回答
1

包含在实体框架中将始终带回关系中的所有内容,无法进行部分包含或 Linq to SQL 具有的 AssociateWith 等效项。

相反,如果您只想带回一些合同,则需要将其拆分为两个查询并利用实体框架执行的自动连接。

一旦执行了两个查询,您的 Person 对象将仅包含由 Contracts 查询在其 Contracts 集合中返回的 Contracts。

于 2010-04-30T13:24:55.800 回答
0

就像 Mant101 所说,您无法将 Linq 中的 .Include 部分过滤为实体。将Person对象视为存储在数据库中有关此人的所有信息的表示,包括所有contracts. 所有的装配都必须单独完成。

这些问题似乎在这里经常出现。至少我想我见过一些,但找不到很多。这是处理这个主题的另一个问题:在 linq 中条件包含到实体?.

那里还有一个可行的分析器:只需以新的匿名类型返回您的(整个)人对象,以及关于它的任何附加(过滤)信息。

于 2010-05-03T10:35:33.850 回答