31

EF モデルからデータを返すメソッドがあります。

上記のメッセージが表示されますが、問題を回避する方法がわかりません。

    public static IEnumerable<FundedCount> GetFundedCount()
    {
        var today = DateTime.Now;
        var daysInMonth = DateTime.DaysInMonth(today.Year, today.Month);

        var day1 = DateTime.Now.AddDays(-1);
        var day31 = DateTime.Now.AddDays(-31);

        using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
        {
            var r = new Repository<MatchHistory>(uow.Context);

            return r.Find()
                .Where(x =>
                    x.AppliedOn >= day1 && x.AppliedOn <= day31 &&
                    x.ResultTypeId == (int)MatchResultType.Accepted)
                .GroupBy(x => new { x.BuyerId, x.AppliedOn })
                .Select(x => new FundedCount(
                    x.Key.BuyerId,
                    x.Count() / 30 * daysInMonth))
                .ToList();
        }
    }

FundedCount は EF エンティティではなく、MatchHistory はそうであるため、なぜ不平を言っているのか理解できません。

すべてのアドバイスに感謝します。

4

4 に答える 4

55

Select()それが不平を言っている理由は、あなたを SQL 式に変換する方法がわからないからです。エンティティではないPOCO にデータ変換を行う必要がある場合は、まず EF から関連データを取得してから、POCO に変換する必要があります。

あなたの場合、以前に呼び出すのと同じくらい簡単なはずですToList()

return r.Find()
        .Where(x => x.AppliedOn >= day1 && x.AppliedOn <= day31 &&
                    x.ResultTypeId == (int)MatchResultType.Accepted)
        .GroupBy(x => new { x.BuyerId, x.AppliedOn })
        .ToList() // this causes the query to execute
        .Select(x => new FundedCount(x.Key.BuyerId, x.Count() / 30 * daysInMonth));

ただし、これには注意してくださいToList()。テーブル全体をメモリにロードしようとしないように、返されるデータ セットのサイズをできるだけ制限してください。

于 2013-06-28T15:12:02.980 に答える
3

FundedCount への参照を SQL ステートメントに変換できないため、不平を言っています。

すべての LINQ プロバイダーは、LINQ ステートメントと式をターゲットが理解できる操作に変換します。LINQ to SQL と LINQ to EF は LINQ を SQL に変換し、PLINQ はそれをタスクと並列操作に変換し、LINQ to Sharepoint はそれを CAML に変換します。

変換できない場合は、プロバイダーによって異なります。一部のプロバイダーは、中間結果を返し、残りのクエリを LINQ to Objects クエリに変換します。他のものは単に失敗してエラー メッセージが表示されます。

データベースと対話するときは、メッセージで失敗する方が実際にはより良いオプションです。そうしないと、サーバーは、実際には 1 つまたは 2 つの列だけが必要なときに、すべての列をクライアントに返す必要があります。

あなたの場合、選択を変更して、必要なデータを含む匿名型を返すようにし、ToList() を呼び出して、FundedCount オブジェクトを作成する必要があります。

.Select( x=> new {Id=x.Key.BuyerId,Count=x.Count()/30 * daysInMonth)
.ToList()
.Select(y => new FundedCount(y.Id,y.Count))
.ToList();

最初の ToList() は、SQL ステートメントの生成を強制し、必要なデータのみを返すクエリを実行します。残りのクエリは実際には Linq to Objects であり、データを取得して最終的なオブジェクトを作成します

于 2013-06-28T15:15:07.680 に答える
3

GroupBy でも同じ例外がありました。「パラメーターなしのコンストラクターとイニシャライザーのみが LINQ to Entities でサポートされています」という例外は、100% 正確な説明ではないことがわかりました。

GroupBy のキーとして構造体を使用する「Linq to EntityFramework クエリ」に GroupBy() がありました。それはうまくいきませんでした。その構造体を通常のクラスに変更すると、すべて正常に機能しました。

コードサンプル

var affectedRegistrationsGrouped = await db.Registrations
  .Include(r => r.Person)
  .Where(r =>
      //whatever
  )
  .GroupBy(r => new GroupByKey
  {
      EventId = r.EventId, 
      SportId = r.SportId.Value
  })
 .ToListAsync();

...
...
// this does not work
private struct GroupByKey() {...}

// this works fine
private class GroupByKey() {...}
于 2014-03-20T09:57:42.457 に答える