2017-11-09 1 views
1

私はこれに似た複数の質問を見ましたが、私のケースは少し異なると思います。私はEF6を使用してデータベースを照会しており、より良い照会のためにデータ投影を使用しています。どのようにEntity Frameworkのネストされたエンティティにマッピング関数を再利用しますか?

このプロジェクトでパフォーマンスが非常に重要であることを考えれば、私が使用する実際のフィールドを読んで、いくつかのフィールドで異なる非常に似たクエリを持っていることを確認しなければなりませんコードの繰り返しので、私はこれは私が持っているもの、現在でコードを再利用する方法について考えてきています:

public static IEnumerable<FundWithReturns> GetSimpleFunds(this DbSet<Fund> funds, IEnumerable<int> fundsId) 
    { 
     IQueryable<Fund> query = GetFundsQuery(funds, fundsId); 

     var results = query 
      .Select(f => new FundWithReturns 
      { 

       Category = f.Category, 
       ExpenseRatio = f.ExpenseRatio, 
       FundId = f.FundId, 
       Name = f.Name, 
       LatestPrice = f.LatestPrice, 
       DailyReturns = f.FundDailyReturns 
            .Where(dr => dr.AdjustedValue != null) 
            .OrderByDescending(dr => dr.CloseDate) 
            .Select(dr => new DailyReturnPrice 
            { 
             CloseDate = dr.CloseDate, 
             Value = dr.AdjustedValue.Value, 
            }), 
       Returns = f.Returns.Select(r => new ReturnValues 
        { 
         Daily = r.AdjDaily, 
         FiveYear = r.AdjFiveYear, 
         MTD = r.AdjMTD, 
         OneYear = r.AdjOneYear, 
         QTD = r.AdjQTD, 
         SixMonth = r.AdjSixMonth, 
         ThreeYear = r.AdjThreeYear, 
         YTD = r.AdjYTD 
        }).FirstOrDefault() 
      }) 
      .ToList(); 
     foreach (var result in results) 
     { 
      result.DailyReturns = result.DailyReturns.ConvertClosingPricesToDailyReturns(); 
     } 
     return results; 
    } 

public static IEnumerable<FundListVm> GetFundListVm(this DbSet<Fund> funds, string type) 
    { 
     return funds 
       .Where(f => f.StatusCode == MetisDataObjectStatusCodes.ACTIVE 
       && f.Type == type) 
       .Select(f => new FundListVm 

       { 
        Category = f.Category, 
        Name = f.Name, 
        Symbol = f.Symbol, 
        Yield = f.Yield, 
        ExpenseRatio = f.ExpenseRatio, 
        LatestDate = f.LatestDate, 
        Returns = f.Returns.Select(r => new ReturnValues 
        { 
         Daily = r.AdjDaily, 
         FiveYear = r.AdjFiveYear, 
         MTD = r.AdjMTD, 
         OneYear = r.AdjOneYear, 
         QTD = r.AdjQTD, 
         SixMonth = r.AdjSixMonth, 
         ThreeYear = r.AdjThreeYear, 
         YTD = r.AdjYTD 
        }).FirstOrDefault() 
       }).OrderBy(f=>f.Symbol).Take(30).ToList(); 
    } 

私はので、私はのFuncを作成してみましたf.Returnsをマップパーツを再利用しようとしています<>以下のようになります。

private static Func<Return, ReturnValues> MapToReturnValues = r => new ReturnValues 
    { 
     Daily = r.AdjDaily, 
     FiveYear = r.AdjFiveYear, 
     MTD = r.AdjMTD, 
     OneYear = r.AdjOneYear, 
     QTD = r.AdjQTD, 
     SixMonth = r.AdjSixMonth, 
     ThreeYear = r.AdjThreeYear, 
     YTD = r.AdjYTD 
    }; 

、その後は次のように使用します。

public static IEnumerable<FundListVm> GetFundListVm(this DbSet<Fund> funds, string type) 
    { 
     return funds 
       .Where(f => f.StatusCode == MetisDataObjectStatusCodes.ACTIVE 
       && f.Type == type) 
       .Select(f => new FundListVm 

       { 
        Category = f.Category, 
        Name = f.Name, 
        Symbol = f.Symbol, 
        Yield = f.Yield, 
        ExpenseRatio = f.ExpenseRatio, 
        LatestDate = f.LatestDate, 
        Returns = f.Returns.Select(MapToReturnValues).FirstOrDefault() 
       }).OrderBy(f=>f.Symbol).Take(30).ToList(); 
    } 

コンパイラはそれでOKですが、実行時に、それがクラッシュすると言う:私はへのFuncを変換しようとした1025

内部の.NET Frameworkデータプロバイダエラーを私はいくつかの質問を読んだ後、compile()を使うような表現ですが、AsEnumerableを使ってもうまくいきませんでした。なぜなら、私が避けたいすべてのフィールドを最初に照会するからです。

私は何かできないことを試みていますか?

ありがとうございます。

答えて

1

間違いなくExpression<Func<...>>である必要があります。ただし、Compile()メソッド(サポートされていません)を使用する代わりに、完全にサポートされているAsQueryable()メソッドを使用してコンパイル時エラーを解決できます(EF6では、現在のEFコアでは機能しません)。

は修正定義

private static Expression<Func<Return, ReturnValues>> MapToReturnValues = 
    r => new ReturnValues { ... }; 

サンプルの使用量が

Returns = f.Returns.AsQueryable().Select(MapToReturnValues).FirstOrDefault() 
+0

はいだろうを考えます!それは働いていて、まったく同じSQL出力を生成しました。近いうちにこれまで...たくさんありがとう –

関連する問題