2

Jeffery Palermoによるタマネギアーキテクチャに基づいた次のアプリケーション構造があります(参照リンク)。つまり、私のコアは何にも依存していません。私のインフラストラクチャは私のコアに依存しています

私のコアにはリポジトリコントラクトがあり、私のインフラストラクチャはそれを実装しています。実装は私のIoCコンテナによって注入されます

Core
-Interfaces
--IRepository<TDomainModel>
-Domain
--Person

Infrastructure
-Data
--Repository<TDomainModel> (Implementation)
-Entities
--Ef.edmx

したがって、具体的なリポジトリの実装(PersonRepositoryなど)を作成した場合、プロジェクト/マップするタイプもわかっているので、これは問題にはなりません。

具体的な実装例:

public class PersonRepository
{
 ...
   public IQueryable<PersonDomainClass> GetByName(string name)
   {
      return Dbcontext.Person.Where(x => x.name == name).Select(x => new Person());
   }
  ...
}

私が欲しいもの:

 public class Repository<TDomainModel> : IRepository<TDomainModel>
 {
     //Problem 1. We can't set the DbSet to a Domain Model
     private DbSet<TDomainModel> dbEntity; 
     ...
       public IQueryable<TDomainModel> GetWhere((Expression<Func<TDomainModel, bool>> predicate))
       {
           //Problem 2. I Don't think this will work because the predicate is ofType TDomainModel    
           //and not an EF Entity!? 
           var entities = dbEntity.Where(predicate);

        var domainObjects = Mapper.Map <IQueryable<TDomainModel>, IQueryable<TEntityModel>> (entities);

        return domainObjects;
       }
      ...
}

私はこれを間違った方法で行っている可能性があるので、他の実装を開きます。

アップデート

みなさんの考えやアドバイスに感謝します。usrは、私が見落としていた非常に良い点を指摘しました。ORMを抽象化すると、ORMが提供するすべての利点が失われます。

私はEFデータベースファースト開発を使用しています。したがって、私のエンティティは、リポジトリの実装とともにインフラストラクチャに含まれています。

タマネギのアーキテクチャに基づいてアプリケーションを構築しているため、ドメインはこれとは別のものです。

私がコードファーストを行っていた場合、最初にドメインを構築し、EFコードを使用してこれをデータベースに変換することが重要なようです。

私は最初にコードを行うことはできません:(

そのため、段階的にEFチーム@MicrosoftのEntityFrameworkDbCotnextPOCOジェネレーターを使用します。これにより、edmxファイルに基づいて永続的な無知なPOCOクラスが生成されます

これは今のところ素晴らしいようです。遅延読み込みと変更の追跡のすべての利点があり、ドメインが生成され、EntityFrameworkが内部でマッピングを処理します。これは私のアプリケーションを簡素化しました:)

したがって、これは私のアーキテクチャの概要ではありません

Core
-Interfaces
--IRepository<TEntity>
---IPersonRepository<Person>
---IFooRepository<Foo>
-Domain
--Person (Auto Generated)
--Foo (Auto Generated)

Infrastructure
-Data
--Repository<TEntity> (Implementation)
---PersonRepository<Person>
---FooRepository<Foo>
-Entities
--Ef.edmx 
4

3 に答える 3

4

リポジトリパターンは、データレイヤーに抽象化を提供するために使用されますか?右?

それを念頭に置いて、LINQ to SQLについて考えてみましょう(EF、nhibernate、またはその他のものを経由するかどうかは関係ありません)。LINQと100%完全に互換性のあるLINQtoSQLプロバイダーはありません。使用できない場合が常にあります。したがって、LINQtoSQLはリークの多い抽象化です。

つまり、公開するリポジトリインターフェイスを使用する場合、IQueryable<TDomainModel>またはExpression<Func<TDb, bool>> whereこれらの制限に注意する必要がある場合です。したがって、これは完全な抽象化ではありません。

代わりに、次のような基本的な汎用リポジトリを提供することをお勧めします。

interface IRepository<TEntity, TKey>
{
    TEntity Get(TKey key);
    void Save(TEntity entity);
    void Delete(TEntity entity);
}

次に、ルートアグリゲート固有のインターフェイスを作成します。

interface IUserRepository : IRepository<User, int>
{
    User GetByUserName(string userName);
    IEnumerable FindByLastName(string lastName);
}

これは、実装が次のようになることを意味します。

public class UserRepository : EfRepository<User>, IUserRepository
{
    //implement the interfaces declared in IUserRepository here
}

リポジトリが提供する機能を簡単に見分けることができる、100%機能する抽象化になりました。今はもう少しコードを書く必要がありますが、後で漏れのある抽象化に苦労する必要はありません。

ここで説明するようなクエリに切り替えることもできます:http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/

于 2012-11-15T09:10:16.727 に答える
1

AutoMapperを見てください。これは、一般的なマッピングに役立つ場合があります。

于 2012-11-14T22:09:03.547 に答える
0

あなたは正しい方向に進んでいますが、ソリューションに抽象化を追加することをお勧めします。

public abstract class RepositoryBase<T, TDb> : where T : new() where TDb : class, new()
{
    protected IQueryable<T> GetBy(Expression<Func<TDb, bool>> where = null,
                                  PagingSortOptions? pagingSortOptions = null)
    {
        //GetDbSet basic method to get DbSet in generic way 
        IQueryable<TDb> query = GetDbSet();

        if (where != null)
        {
            query = query.Where(where);
        }

        if (pagingSortOptions != null)
        {
            query = query.InjectPagingSortQueryable(pagingSortOptions);
        }

        return query.Select(GetConverter());
    }

    protected virtual Expression<Func<TDb, T>> GetConverter()
    {
        return dbEntity => Mapper.Map<TDb, T>(dbEntity);
    }
}

public class CountryRepository : RepositoryBase<CountryDomainModel, CountryDb>, ICountryRepository
{
    public Country GetByName(string countryName)
    {
        return GetBy(_ => _.Name == countryName).First();
    }
}

public interface ICountryRepository : IRepository<CountryDomainModel>
{
    Country GetByName(string countryName);
}

public interface IRepository<TDomainModel>
{
    //some basic metods like GetById
}

データベース層の外側よりも使用しますICountryRepository

于 2012-11-14T22:12:30.113 に答える