2017-06-01 11 views
0

DbFunctionsクラスを使用して日付を計算する式があります。それはlinq-to-entitiesのためにうまく動作しますが、私は非db機能のためにこの表現を再利用したいと思います。 expressionがdbコンテキストで評価されるかどうかを検出し、対応する実装を使用することは可能ですか?私はモックオブジェクトを含む単体テストの解決策を見てきましたが、一般的なビジネスロジックでこの表現が必要なので、モックは良い解決策のようには見えません。私はこのような何かをできるようにしたいコンテキストに応じてDbFunctionsをdb以外の実装に切り替えます

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

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

MyCustomResolverは、文脈に応じて、どちらかDbFunctionsまたはDateTime実装を使用する場所

は、ここに私の表現です。今

答えて

0

は最後に、私は次のようなアプローチを使用:

  1. DbFunction属性を持つ関数を定義します。 LINQのツーエンティティ式またはC#の機能で使用される場合

  2. 非デシベルコンテキストで

    /// <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); 
        } 
    } 
    
  3. を実行した場合、この方法には、

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

、私は1つが、オンザフライAddMinutes内決意を作ることができます想像しますが、なぜですか?毎回if()を実行する方が良いです。

+0

上で定義されたヘルパー関数を使用してビルド式を、対応するSQL関数を使用しています問題は、内部表現ではdbと呼ばれる情報がないので、毎回明示的に渡さずに実際のコンテキスト(この 'amIUsingDB'値)を検出する方法が問題です。 – Random

+0

"なぜ"実際の表現はより複雑であり、私は、dbとnon-dbコンテキストのたびに2つの別々の実装を書くためのオーバヘッドのように見えるので、実際のコンテキストに応じた式があるときは、(AddMinutesのような)特定のメソッドの正しい実装を選択できるのだろうかと思います。 。 – Random

+0

@Random Exactly - 両方のコメント。だからこそ私は 'amIUsingDB' *の評価を関数の外部*に移しました。その時点で必要なリゾルバに 'MyCustomResolver'を設定して、その情報を知ってからもう一度心配することはありません。これで、あなたがあなたの質問に与える 'Expired'メソッドは、あなたが望むように動作することに注意してください。 –

関連する問題