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

このクエリの最後に、各人が次のようなデータを入力したオブジェクトグラフが必要です。

  • PesonAddressの
  • PesonPhoneの
  • PesonEmailの
  • PesonPhoneの
  • 契約-そしてこれにはそれぞれがあります
    • プログラムの

今、私は次のクエリを持っていて、それはうまく機能していると思いましたが、いくつかの問題があります:

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の契約だけでなく、各契約の各プログラムにも同じことが当てはまるすべての契約が復活します。

私が欲しいのは、OrgIdがxで少なくとも1つのコントラクトを持ち、そのコントラクトがyのIdでプログラムを持っている人だけです...そして返されるオブジェクトグラフには、一致するコントラクトだけがあります。一致するその契約内のプログラム。

なぜ機能しないのかはわかりますが、変更方法がわからないので機能しています...

これはこれまでの私の試みです:

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オブジェクトである場合)。

  • 私は自分でマッピングを行う必要があります。この場合、マッピングするものはかなりたくさんあります。
  • リストをプロパティにマップしようとすると(つまり、Scholarship = currentScholarships)、IEnumerableキャストしようとしているためにマップできないと表示されます。EntityCollection
  • インクルードが機能しない

したがって、これを機能させるにはどうすればよいですか。私はこれをコンパイルされたクエリとして実行しようとしていることを念頭に置いて、匿名型が出ていることを意味すると思います。

4

3 に答える 3

2

インクルードを使用せず、手動でフィルタリングします。最初に、必要なProgramIdおよびOrganizationIdに関連付けられているコントラクトをフィルタリングできます。その後、選択した契約に関連付けられている人を選択できます。サンプルコードを添付しました。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

Entity Frameworkに含めると、関係内のすべてが常に元に戻ります。LinqtoSQLが持つ部分的なインクルードまたはAssociateWithと同等の機能を実行する方法はありません。

代わりに、一部のコントラクトのみを戻したい場合は、それを2つのクエリに分割し、エンティティフレームワークによって実行される自動フックアップを利用する必要があります。

両方のクエリが実行されると、Personオブジェクトには、ContractsコレクションのContractsクエリによって戻されたContractsのみが含まれます。

于 2010-04-30T13:24:55.800 に答える
0

Mant101が言うように、Linqの.Include部分をエンティティにフィルタリングすることはできません。Personすべてを含む、この人物に関するデータベースに保存されているすべての情報の表現としてオブジェクトを見てくださいcontracts。すべてのフィッティングは個別に行われます。

これらの質問はここで定期的に出てくるようです。少なくとも私はいくつか見たと思いますが、多くを見つけることができません。このトピックを扱う別の質問があります:エンティティへのlinqに条件付きインクルード?

そこには実行可能な回答もあります。(全体の)人物オブジェクトと、そのオブジェクトに関する追加の(フィルタリングされた)情報を新しい匿名タイプで返すだけです。

于 2010-05-03T10:35:33.850 に答える