4

場合によっては、いくつかのビジネス ルールを定義する必要があり、仕様パターンが便利なツールになります。例えば:

public class CanBorrowBooksSpec : ISpecification<Customer>
{
    public bool Satisfies(Customer customer)
    {
         return customer.HasLibraryCard
              && !customer.UnpaidFines.Any();
    }
}

しかし、パフォーマンスを改善したり、ページ化されたレコードのリストなどに対応したりするために、これらのルールを SQL に「プッシュ」する必要があることがよくあります。

その後、ルールのコードを 2 回 (CLR コードで 1 回、SQL (または ORM 言語) で 1 回) 記述する必要があります。

このようなコードをどのように整理しますか?

コードを同じクラスにまとめておくのが最善のようです。そうすれば、開発者がビジネス ルールを更新する場合に、両方のコード セットを更新するのを忘れる可能性が少なくなります。例えば:

public class CanBorrowBooksSpec : ISpecification<Customer>
{
    public bool Satisfies(Customer customer)
    {
         return customer.HasLibraryCard
              && !customer.UnpaidFines.Any();
    }

    public void AddSql(StringBuilder sql)
    {
        sql.Append(@"customer.HasLibraryCard 
                     AND NOT EXISTS (SELECT Id FROM CustomerUnpaidFines WHERE CustomerId = customer.Id)");
    }
}

しかし、私たちは今懸念を混ぜ合わせているので、これは私にはかなり醜いようです。

もう 1 つの方法は、LINQ コードをコレクションに対して実行するか、SQL に変換できるため、Linq-To-YourORM ソリューションを使用することです。しかし、最も些細なシナリオ以外では、そのような解決策はめったに不可能であることがわかりました。

職業はなんですか?

4

1 に答える 1

4

Entity Framework で Specification パターンを使用しました。これが私たちがそれにアプローチした方法です

public interface ISpecification<TEntity>
{
    Expression<Func<TEntity, bool>> Predicate { get; }
}


public class CanBorrowBooksSpec : ISpecification<Customer>
{
    Expression<Func<Customer, bool>> Predicate 
    { 
       get{ return customer => customer.HasLibraryCard
              && !customer.UnpaidFines.Any()} 
    }
}

次に、次のような LINQ-to-Entities に対して使用できます

db.Customers.Where(canBorrowBooksSpec.Predicate);

LINQ-to-Objects のように

customerCollection.Where(canBorrowBooksSpec.Predicate.Compile());
于 2011-08-26T07:26:58.667 に答える