2017-11-09 3 views
1

Ich habe mehrere Fragen gesehen, die denen ähnlich sind, aber ich denke, mein Fall ist etwas anders. Ich verwende EF6, um die Datenbank abzufragen, und ich verwende Datenprojektion für bessere Abfragen.Wie werden die Zuordnungsfunktionen für verschachtelte Entitäten in Entity Framework wiederverwendet?

Angesichts der Leistung ist sehr wichtig für dieses Projekt muss ich sicherstellen, nur die tatsächlichen Felder zu lesen, die ich verwenden werde, so habe ich sehr ähnliche Abfragen, die für nur ein paar Felder unterschiedlich sind, wie ich dies getan habe, habe ich bemerkt Wiederholung des Codes so denke ich worden, wie die Wiederverwendung von Code ist dies zur Zeit, was ich habe:

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(); 
    } 

ich versuche, den Teil wieder zu verwenden, wo ich die f.Returns Karte so habe ich versucht, schaffte eine Func <> wie folgt:

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 
    }; 

und verwenden Sie dann wie folgt aus:

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(); 
    } 

Der Compiler ist mit ihm in Ordnung, aber zur Laufzeit, stürzt es und sagt: Internal .NET Framework Data Provider Fehler 1025

Ich versuchte, die Func zu umwandeln in Ausdruck, wie ich in einigen Fragen gelesen habe und dann compile() benutze, aber es nicht funktionierte, AsEnumerable zu benutzen, ist auch keine Option, weil es alle Felder zuerst abfragt, was ich vermeiden will.

Ich versuche etwas nicht möglich?

Vielen Dank für Ihre Zeit.

Antwort

1

Es muss auf jeden Fall Expression<Func<...>> sein. Aber anstatt die Methode Compile() (nicht unterstützt) zu verwenden, können Sie den Kompilierzeitfehler mit der Methode AsQueryable() beheben, die perfekt unterstützt wird (in EF6 funktioniert der Trick nicht im aktuellen EF Core).

die modifizierte Definition

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

die Probe Nutzung

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

Ja! das war es funktioniert und es produziert genau die gleiche SQL-Ausgabe, so nah noch so weit ... Vielen Dank –

Verwandte Themen