3

背景:アプリケーションには複数のレイヤーがあり、そのうちの2つはドメインレイヤーとDALとして機能するインフラストラクチャレイヤーです。ドメイン層では、次のような汎用リポジトリパターンを実装しました。

    public interface IRepository<T, in TId> where T : IEntity<TId>
    {
        void Insert(T entity);
        void Delete(T entity);
        IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
        IQueryable<T> GetAll();
        T GetById(TId id);
    }

私のDALには、一般的なDAOパターンが次のように実装されています。

    public interface IDao<TEntity> where TEntity : class
    {
        IQueryable<TEntity> Select();
        IQueryable<TEntity> GetAll();
        IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate);
        TEntity GetSingle(Expression<Func<TEntity, bool>> predicate);
        TEntity GetFirst(Expression<Func<TEntity, bool>> predicate);
        void Add(TEntity entity);
        void Delete(TEntity entity);
        void Attach(TEntity entity);
    }

私は、ビジネス用語で個人を表すドメインクラスを持っています。DALレイヤーには、データベース内のオブジェクトを表すために使用される同様の個別のオブジェクトがあります。IDAOインターフェイスを実装し、そのDAOインターフェイスで見つかったすべてのアクション(CRUDおよび上記のその他のアクション)を担当するEntityFrameworkDaoというクラスがあります。

リポジトリで使用されている式をDALで使用されている式にマップする方法を見つけようとしています(何日も試しています)。具体的な例は次のとおりです。IRepositoryインターフェイスを実装する汎用DomainRepositoryがあります(上記を参照)。SearchForメソッドは次のようになります。

        public IQueryable<TDomainEntity> SearchFor(Expression<Func<TDomainEntity, bool>> predicate)
    {
        var convertedExpression = **SomeMagicFunctionToConvertExpressions**();
        var dataEntities = _dao.Where(convertedExpression);
        return AutoMapper.Mapper.Map<IEnumerable<TEfEntity>, IEnumerable<TDomainEntity>>(dataEntities).AsQueryable();
    }

ドメインレイヤーの述語を、IDaoを実装するDALクラスでWhereメソッドが理解できるものに変換できるように、SomeMagicFunctionToConvertExpressionsが何であるかを理解する必要があります。

        public IQueryable<TEfEntity> Where(Expression<Func<TEfEntity, bool>> predicate)
        {
            return _context.Set<TEfEntity>().Where(predicate).AsQueryable();
        }

この記事にあるAutomapperのCreateMapExpressionを使用してみました:セレクタータイプ間のFuncのAutoMapper

しかし、それは、式から式へではなく、Func<DomainType,bool>述語から(述語)への変換方法を教えてくれるだけです。Func<DTOType,bool>私はこのようなものを変換する方法を探しています:

Expression<Func<TDomainEntity, bool>> predicate

これに:

Expression<Func<TDAOEntity, bool>> predicate

式ツリーの変更に関するこの記事を見つけた後、何かに取り組んでいると思いましたが、&&または||を含む複雑なlinq式を渡すことができません。または、単純なi => i.id.Equals(12345)タイプのクエリよりも複雑なもの。

私はAutomapperを使用しているので、それを使用しているsolutoinはどれも素晴らしいでしょうが、現時点ではどんなアイデアも受け入れています。私は本当に立ち往生していて、これを何日も研究しています。これはかなり一般的なタスクのようです。タイプに基づくクエリを、アーキテクチャ内の1つのレイヤーからDALで使用されるタイプに変換します。

よろしくお願いします。

4

1 に答える 1

2

おそらくこれを行うべきではありません。物事を複雑にしすぎているようです。

まず、一般的なリポジトリ パターンを使用すると、基本的にTDAの原則に違反します。ストレージの実装への直接的な依存関係を作成しています。汎用リポジトリに「すべて」、「ID による」、および「全文検索」を含めることは問題ありませんが、それ以外はインターフェイスで非表示にする必要があります。簡単な例:

repo.search(x=>x.IsActive==true)

これが単純なフラグであり、何らかの形で後でドメインがどこかで変更され、アイテムもソフト削除できると判断したとします。これは、ドメイン内のすべてのコードを前者から次のように変更する必要があることを意味します。

repo.search(x=>x.IsActive==true && x.IsDeleted == false)

これを行う適切な方法は、このようにリポジトリに適切なメソッドを用意することです

repo.ActiveItems()

これにより、行動がどこにでも広がることはありません。

次に、一般的な検索を公開している場合は、ドメイン モデルで直接 Linq を使用しないでください。結局のところ、まだ SQL オブジェクトの別のレイヤーの上にレイヤーを実装しているのです。これらの余分なレイヤーを追加することの付加価値について説明していただけますか? 結局のところ、それらはまだ同じ実装に関連付けられています (ただし、名前と値の変換が追加されている可能性があります)。

于 2013-05-11T07:19:10.323 に答える