2017-06-01 2 views
0

Ich habe einen Ausdruck, der DbFunctions-Klasse verwendet, um Daten zu berechnen. Es funktioniert gut für linq-to-entities, aber ich möchte diesen Ausdruck für Nicht-DB-Funktionalität wiederverwenden. Ist es möglich, zu erkennen, ob Ausdruck im Db-Kontext ausgewertet wird oder nicht, und entsprechende Implementierung zu verwenden? Ich habe Lösungen für Komponententests gesehen, die Mock-Objekte beinhalten, aber ich brauche diesen Ausdruck in der üblichen Geschäftslogik, damit Mocks nicht wie eine gute Lösung aussehen.DbFunctions zu einer non-db-Implementierung je nach Kontext wechseln

Hier ist mein Ausdruck:

public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod) 
{ 
    return s => s.Status == Status.Created && DbFunctions.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow; 
} 

Ich möchte in der Lage sein, so etwas zu tun:

public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod) 
{ 
    return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow; 
} 

wo MyCustomResolver wird je nach Kontext entweder DbFunctions oder DateTime Implementierung verwenden.

Antwort

0

Schließlich habe ich den folgenden Ansatz:

  1. eine Funktion mit DbFunction Attributen definieren. Auf diese Weise nutzt entsprechende SQL-Funktion verwendet, wenn in Linq to Entities Expression oder Funktion C#, wenn Kontext in nicht-db ausgeführt

    /// <summary> 
    /// Utilize functions for both Linq-to-Entities and non-db context 
    /// </summary> 
    public static class MyCustomResolver 
    { 
        [DbFunction("Edm", "AddMinutes")] 
        public static DateTime? AddMinutes(DateTime? timeValue, int addValue) 
        { 
         return timeValue?.AddMinutes(addValue); 
        } 
    } 
    
  2. Ausdrücke Helferfunktion oben

    public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod) 
    { 
        return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow; 
    } 
    
    definiert bauen mit
0
interface ICustomResolver 
{ 
    DateTime AddMinutes(DateTime, int); 
} 

public class DbCustomResolver : ICustomResolver 
{ 
    public DateTime AddMinutes(DateTime time, int minutes) 
    { 
     return DbFunctions.AddMinutes(time, minutes); 
    } 
} 

public class NonDbCustomResolver : ICustomResolver 
{ 
    public DateTime AddMinutes(DateTime time, int minutes) 
    { 
     return time.AddMinutes(minutes); 
    } 
} 


ICustomResolver MyCustomResolver = 
    amIUsingDB ? new DbCustomResolver() : new NonDbCustomResolver(); 

Nun stelle ich einen die Bestimmung machen könnte innerhalb AddMinutes on-the-fly, aber warum? Es ist besser, die if() einmal zu tun, anstatt es jedes Mal zu tun.

+0

Das Problem ist, dass innerhalb Ausdruck habe ich keine Informationen, wenn es für db aufgerufen wird oder nicht, so ist die Frage, wie man den tatsächlichen Kontext (diese 'amIUsingDB' Wert) erkennen, ohne es jedes Mal explizit übergeben – Random

+0

Was" warum " , die tatsächlichen Ausdrücke sind komplizierter und Es sieht für mich wie ein Overhead aus, dass ich jedes Mal zwei separate Implementierungen für den db- und den non-db-Kontext schreibe. Daher frage ich mich, ob ich die richtige Implementierung bestimmter Methoden (wie 'AddMinutes') auswählen kann, wenn ein Ausdruck vom tatsächlichen Kontext abhängt . – Random

+0

@Random Genau - zu beiden Kommentaren. Deshalb habe ich die Auswertung von 'amIUsingDB' * außerhalb * der Funktion verschoben. Sie setzen 'MyCustomResolver' einmal auf den Resolver, den Sie benötigen, um diese Informationen zu kennen, und sich dann nie wieder darum zu kümmern. Beachten Sie, dass damit die "Expired" -Methode, die Sie in Ihrer Frage angeben, so funktioniert, wie Sie möchten. –

Verwandte Themen