2011-01-26 24 views
1

私はLinqToSQLを使用して、多くの項目を含むIN節を生成しようとしています。私の元のコードは、次のようなものでした。LinqToSQL句内

context.Employees.Where(p => EmployeeIDs.Contains(p.EmployeeID)); 

これは、各従業員IDがSQLパラメータとしてin節を生成することになります。問題は、2100を超えるパラメータを渡すと例外がスローされることです。私は複数のクエリを実行し、結果を組み合わせることで、アプリケーションの他の場所で作業しました。それは単純なケースでは大丈夫ですが、私はもう少し複雑なことをやっています。これが最善の解決策ではないと思います。とにかく、含まれてい

EmployeesID IN (@p0, @p1, @p2) 

のようなものを生成しますが、これを行うには、それを説得する方法はありますか?

EmployeesID IN (23, 582, 3948) 

私は、動的なクエリの例を使用しての道を行き始めたが、その後、動的LINQコードではなく、動的SQLを書くためであると考えられることに気づきました。それから、ExecuteQueryが見つかりましたが、私が望むクエリの特定のセクションだけを手動で作成することはありません。 (これは、パラメータを使用せずに、IN生成する場合)

context.Employees 
    .Where(p => p.Active == true) 
    .Where("EmployeeID IN (23, 582, 3948)"); 

またはできれ:

具体的には、私のような何かをしたいと思います

context.Employees 
    .Where(p => p.Active == true) 
    .Where(p => p.In("EmployeeID", EmployeeIDs)); 

これを行うにはどのような方法を?ありがとう。

答えて

0

他のクエリに基づいて必要な従業員IDを返すクエリを定義できますか?その場合は、ネストされたクエリを使用して検索を定義することができます。

var employeeIds = from x in context.EitherEmployeesOrSomeOtherRecords 
    where x.SomeConditionIsTrue 
    select x.EmployeeID; //not yet evaluated; employeeIds is an IQueryable 

var employees = from e in context.Employees 
    where employeeIds.Contains(x.EmployeeID) 
    select e; 

このLINQクエリは、単一のSQL文にLinq2SQLによって消化されるemployeeIdsサブクエリのSQL同等物をチェックする句をEXISTS使用します。

Linq2SQLにリテラルとしてコードの値を指定させる限り、私はできないと思っていますが、間違っている可能性があります。

EDIT: OKこれで、クエリをよりスマートに構築する方法を決定するロジックを作成したらどうでしょうか?ユーザーが選択した場合

var employees = from e in context.Employees 
    where TheSameConditionThatCausedItToBeInTheList == true 
    select e; 

:あなたは「すべて選択」ボタンやチェックボックスを使用している場合と同様に、あなたは、単純なクエリを作る「リストのために選択されていたであろうすべての従業員をプルアップ」することを使用することができます

var notChecked = uiList.Items.Except(uiList.SelectedItems).Select(x=>x.EmployeeID) 

var employees = from e in context.Employees 
    where !notChecked.Contains(e.EmployeeID) 
    select e; 

あなたは以上の4200人の従業員を持っている場合は、上記のすべて、その後は、あなたが(もっとないより選択)ことを検出し、代わりに「X、Y、およびZ以外のすべての従業員を」引き上げることができ、いくつかの選択を解除しました常に動作するとは限りません(あなたは2100以上を選択できますが、2100以上は選択しないのでどちらかが爆発します)が、baを選択できない4200項目のリストも想像できませんいくつかの他の指標(すなわち、部門)、「X、YおよびZ部門のすべての従業員を引き上げ、また、従業員A、BおよびC」のようなクエリを許可する:

var metaSelection = departmentList.SelectedItems.Select(x=>x.DepartmentID); 

var exceptions = uiList.SelectedItems.Where(x=>!metaSelection.Contains(x.DepartmentID)) 
         .Select(x=>x.EmployeeID); 

var employees = from e in context.Employees 
    where metaSelection.Contains(e.DepartmentID) 
    || exceptions.Contains(e.EmployeeID) 
+0

ネストされたクエリの代わりに 'join'を使用して、別のバージョンのサンプルを含めることができます。私はあなたのものに似た何かを投稿していたので、ただの提案です。 – shaunmartin

+0

私の場合、従業員IDはユーザーによって提供されます。従業員のリストが表示され、必要なものを選択します。だから私はこれがうまくいくとは思わない。 – Dan

+0

私はあなたが示唆したように、よりスマートなクエリを作成しようと考えました。それがうまくいくかどうかはわかりません。ユーザーが望んでいなかったレコードが含まれる可能性があることがわかります。たとえば、アクティブなすべての従業員のリストが表示され、次に他のユーザーがアクティブなデータを更新した場合、最初のユーザーは結果を表示するために何かを行い、現在は間違った従業員が含まれます。 – Dan

0

ここでの問題は、2100個のパラメータの制限です。これはSQLによって定義されたハードな制限です。 ADO.NETまたはLINQではありません。私は数週間前にこの壁に遭遇しました。 LINQは常にクエリのパラメータを設定するので、その回りには方法がありません。呼び出しをバッチするか、ExecuteQueryを使用する必要があります。しかし、ExecuteQueryを使用する場合は、SQLインジェクション攻撃を避けるために、パラメータに対して独自の検証を行うようにしてください。