0

主キーが 2 つの外部キーの合成である純粋な多対多を想定しています。たとえば、Northwind の「Employee Privileges」には EmployeeID と PrivilegeID があります。この m2m は明らかに、Employees テーブルを Privilege テーブルに関連付けます。

EF を使用して、他の PrivilegeID に関連しているかどうかに関係なく、指定された PrivilegeID に関連付けられていないすべての従業員を返すクエリを作成する必要があります。

Sql Server では機能する EF クエリがありますがExcept()、Oracle では機能しません。

t-sql でクエリを作成している場合、従業員特権を必要な特権でフィルター処理するクエリを作成します。「以下の EmpPrivQuery を参照してください」。次に、EmployeesMissingPrivileges に見られるように、EmpPrivQuery を Employee に直接結合して、フィルターを完成させます。

現在、多対多テーブルを作成するためのリレーションシップ プロパティを持つ Employee モデルと Privilege モデルがあります。プロジェクトでは、最初に EF コードを使用してスキーマを作成します。

これは EF 結合構文で実行できますか? EmployeePrivilege テーブルのエンティティ モデルを作成せずに実行できますか?

EmpPrivQuery:
SELECT [Employee Privileges].[Employee ID], [Employee Privileges].[Privilege ID] 
FROM [Privileges] INNER JOIN [Employee Privileges] ON Privileges.[Privilege ID] = [Employee Privileges].[Privilege ID]
WHERE (((Privileges.[Privilege Name])="P3"));


EmployeesMissingPrivileges:
SELECT EmpPrivQuery.[Employee ID], Employees.*
FROM Employees LEFT JOIN EmpPrivQuery ON Employees.ID = EmpPrivQuery.[Employee ID]
WHERE (((EmpPrivQuery.[Employee ID]) Is Null));

このブロックは元の投稿にありましたが、質問を曇らせます。コメント コンテキスト用に保持されます。 Oracle データ プロバイダーとして Devart dotConnect を使用しています。Oracle がスローしているエラーはORA-00904: "Extent1"."EmployeeID": invalid identifier. SQL Server 用に作成されたコード ベースを Oracle で動作するように適合させる際に、これは解決する必要がある一般的なエラーです。ほとんどの場合、SelectMany() を使用して、クエリを書き直して、他のテーブルへのリレーションシップを WHERE 述語 (動的にするのが非常に簡単な場所) からクエリの本体に移動することで解決できました。これにより、データベース サーバーに送信されるクエリが平坦化される傾向があり、Oracle はそれを必要とするようです。

4

1 に答える 1

1

EF を使用して、質問に投稿されたものと基本的に同じクエリを作成できます。まず、プロパティ int PrivilegeID と int EmployeeID を持つ poco モデル EmployeePrivilege を作成しました。これを DbContext に追加しませんでした。

var EmpPrivQuery = ctx.Privileges
                       .Where(p => p.PrivilegeName == "P3")
                       .SelectMany(p => p.Employees, (p, e) => new EmployeePrivilege{EmployeeID = e.EmployeeID, PrivilegeID = p.PrivilegeID}
                       .Distinct();

var employeesMissingPrivilege = from e in Employees
                                join epq in EmpPrivQuery
                                on e.EmployeeID equals epq.EmployeeID
                                into jointable
                                where jointable.Count()==0
                                select e;

次のように poco EmployeePrivilege を作成しなくても同じ結果が得られることに気付きました。

var EmpPrivQuery = ctx.Privileges
                        .Where(p => p.PrivilegeName == "P3")
                        .SelectMany(p => p.Employees.Select(e => e.EmployeeID)
                        .Distinct();

var employeesMissingPrivilege = from e in Employees
                                join epq in EmpPrivQuery
                                on e.EmployeeID equals epq
                                into jointable
                                where jointable.Count()==0
                                select e;

これらの EF クエリは両方とも、Sql Server と Oracle の両方に対して (Devart の dotConnect for Oracle を使用して) 従業員に指定された特権が不足していることを返します。

私が読んだ多くの記事ではDefaultIfEmpty()、左外部結合を実現するために使用する方法について言及していました。上記のクエリは機能しますが、 を使用してこの結果を得るより良い方法がある場合は投稿してくださいDefaultIfEmpty()

于 2012-12-27T20:07:22.127 に答える