89

私はこのlinqクエリを持っています:

private void GetReceivedInvoiceTasks(User user, List<Task> tasks)
{
    var areaIds = user.Areas.Select(x => x.AreaId).ToArray();

    var taskList = from i in _db.Invoices
                   join a in _db.Areas on i.AreaId equals a.AreaId
                   where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
                   select new Task {
                       LinkText = string.Format(Invoice {0} has been received from {1}, i.InvoiceNumber, i.Organisation.Name),
                       Link = Views.Edit
                   };
}

ただし、問題があります。タスクを作成しようとしています。リンクテキストを「Hello」のような定数文字列に設定すると、新しいタスクごとに問題ありません。ただし、上記では、請求書のプロパティを使用してプロパティ リンクテキストを作成しようとしています。

次のエラーが表示されます。

base {System.SystemException} = {"LINQ to Entities はメソッド 'System.String Format(System.String, System.Object, System.Object)' メソッドを認識せず、このメソッドをストア式に変換できません。" }

理由を知っている人はいますか?これを機能させるための別の方法を知っている人はいますか?

4

3 に答える 3

151

Entity Framework は、に相当するものがない SQL 側でプロジェクションを実行しようとしていますstring.FormatAsEnumerable()Linq to Objects でその部分の評価を強制するために使用します。

以前の回答に基づいて、クエリを次のように再構築します。

int statusReceived = (int)InvoiceStatuses.Received;
var areaIds = user.Areas.Select(x=> x.AreaId).ToArray();

var taskList = (from i in _db.Invoices
               where i.Status == statusReceived && areaIds.Contains(i.AreaId)
               select i)
               .AsEnumerable()
               .Select( x => new Task()
               {
                  LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.Organisation.Name),
                  Link = Views.Edit
                });

また、クエリで関連するエンティティを使用していることがわかります ( Organisation.Name) クエリに適切なものを追加するかInclude、後で使用するためにそれらのプロパティを明確に具体化してください。

var taskList = (from i in _db.Invoices
               where i.Status == statusReceived && areaIds.Contains(i.AreaId)
               select new { i.InvoiceNumber, OrganisationName = i.Organisation.Name})
               .AsEnumerable()
               .Select( x => new Task()
               {
                  LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.OrganisationName),
                  Link = Views.Edit
                });
于 2012-04-09T21:21:36.973 に答える
15

IQueryableから派生しIEnumerableます。主な類似点は、クエリを作成すると、その言語でデータベース エンジンに投稿されることです。薄い瞬間は、C# にサーバー (クライアント側ではなく) でデータを処理するように指示するか、SQL に処理を指示することです。データ。

したがって、基本的にはIEnumerable.ToString()、C# はデータ コレクションを取得ToString()し、オブジェクトを呼び出します。しかし、IQueryable.ToString()C#はSQLにToString()オブジェクトを呼び出すように指示しますが、SQLにはそのようなメソッドはありません。

欠点は、C# でデータを処理する場合、C# がフィルターを適用する前に、調べているコレクション全体をメモリに構築する必要があることです。

これを行う最も効率的な方法は、IQueryable適用できるすべてのフィルターと同じようにクエリを作成することです。

そして、それをメモリに構築し、C# でデータの書式を設定します。

IQueryable<Customer> dataQuery = Customers.Where(c => c.ID < 100 && c.ZIP == 12345 && c.Name == "John Doe");

 var inMemCollection = dataQuery.AsEnumerable().Select(c => new
                                                  {
                                                     c.ID
                                                     c.Name,
                                                     c.ZIP,
                                                     c.DateRegisterred.ToString("dd,MMM,yyyy")
                                                   });
于 2013-05-17T06:29:25.353 に答える