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はそうであるため、不満の理由を理解できません。
すべてのアドバイスに感謝します。
文句を言うのは、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()
によって返されるデータセットのサイズをできるだけ制限するようにしてください。
メッセージは明確です:エンティティへのlinqは、パラメーターなしのctorのないオブジェクトをサポートしません。
そう
Solution1
前に列挙する(または中間の匿名型を使用して、その上で列挙する)
.ToList()
.Select(x => new FundedCount(
x.Key.BuyerId,
x.Count() / 30 * daysInMonth))
.ToList();
Solution2
fundedCountクラスにパラメーターなしのctorを追加します(可能な場合)
public FundedCount() {}
そして使用する
.Select(x => new FundedCount{
<Property1> = x.Key.BuyerId,
<Property2> = x.Count() / 30 * daysInMonth
})
.ToList();
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であり、データを取得して最終的なオブジェクトを作成します
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() {...}