Allメソッドは、リスト内のすべての要素に対して引数を評価します。これは通常のLinqでは問題なく動作しますが、EFと一緒に使用しようとするとエラーが発生します。文脈。 ")
例:
var myList = from person in entities.People
where searchList.All(arg => arg == arg).ToList();
(arg == argは私の質問を説明するためだけのものです)
私のシナリオでは、searchListは、 "John"、 "Accounting"、 "75"などの検索項目を含むリストです。私のEFクエリで、John、Accounting、および75が、特定の検索可能フィールドに表示されているPeopleのすべてのレコードを取得します。より現実的な例は、次のようになります。
where SearchList.All((person.FirstName + " " + person.LastName + " " + person.DepartmentName + " " + person.Phone).Contains)
2番目の例も、メモリ内のLinqで問題なく機能しますが、EFはそれを好まない。
助けてください!それを機能させるために私は何ができますか?
これは私の別の質問から派生したより具体的な質問です。
IEnumerable<string> searchList = ParseSearchText(searchText); //search text is broken into search tokens - each token is an element in searchList. For instance "John", "Sales", "654"
var peopleQuery = from person in entities.vSearchPeople
where upperSearchList.All((person.FirstName + " " + person.Lastname + " " + person.Phone).ToUpperInvariant().Contains)
select person;
Entity Frameworkはすべてのクエリをサポートするわけではありません。次のように考えると、これは明らかになります。
dataContext.Persons.Where(person => MyMethod(person));
MyMethod()
がブール値を返します。メソッドがすべてを実行する可能性があり、すべてをSQLに変換することはできません。解決策は、 ToList()
を使用してすべてのエンティティをローカルメモリに格納してから、LINQ to Objectを使用することです。
dataContext.Persons.ToList().Where(person => MyMethod(person));
書き換え可能かどうかは、実際のクエリによって異なります。そのため、Entity FrameworkによってSQLに変換できる場合や、LINQ to Objectを使用してローカルメモリでクエリを実行する必要がある場合は異なります。
あなたが言及した例外は、あなたが次のようなことを試みているように聞こえます。
Company company = datacontext.Companies.Where(company.Name == "ACME").Single();
dataContext.Employees.Where(employee => employee.Company == company);
LINQ to Entityは、エンティティを含む式をサポートしていないため、 Company
エンティティの比較は無効です。この場合は、次のように書き換えることができます。
dataContext.Employees.Where(employee => employee.Company.Id == company.Id);
これは、id(整数やGUIDなどのプリミティブ型)のみを比較し、これをSQLに変換できます。
単語単位の検索の例(コメントも参照)
IQueryable<People> result = entities.People;
foreach (String item in searchList)
{
// This copy is important in order not to modify the closure.
String itemCopy = item;
result = result.Where(p =>
p.FirstName.ToUpper().Contains(itemCopy) ||
p.LastName.ToUpper().Contains(itemCopy) ||
p.Phone.ToUpper().Contains(itemCopy));
}
これは単語単位でクエリを構築します。 Entity FrameworkがToUpper()
、 ToLower()
、およびContains()
(およびその他)を認識することにToUpper()
、Entity Frameworkがメソッド呼び出しを認識しないと言ったときは厳密にしなければなりませんでした。それはしますが、 ToUpperInvariant()
やToLowerInvariant()
ToUpperInvariant()
。さらにこのクエリは、列の照合順序を使用したCHARINDEX()
関数呼び出しに変換されるため、 ToUpper()
またはToLower()
を明示的にToUpper()
ない限り、検索で大文字と小文字が区別されないことがあります。
この良い例は、All()メソッドで何がうまくいっているかです。
model.ReferenceList = db.JournalCardReference.OrderBy(a => a.orderF)
.Include(x => x.JournalCardField)
.Where(x => x.JournalCardField
.All(f => f.deleted == null || f.deleted != true)).ToList();