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 Database First 开发。所以我的实体与我的存储库实现一起在我的基础设施中。

域与此分开,因为我正在基于洋葱架构构建我的应用程序。

如果我在做 Code First,似乎要做的事情是先构建您的域,然后使用 EF Code 首先将其转换为数据库。

我不能先写代码:(

因此,EF 团队 @Microsoft 的实体框架 DbCotnext POCO 生成器分步进行。这会根据我的 edmx 文件生成持久的无知 POCO 类

到目前为止,这似乎很棒,我拥有延迟加载和更改跟踪的所有好处,甚至更好地为我生成了我的域,并且实体框架在内部处理映射。这简化了我的应用程序:)

所以这不是我的架构的高级视图

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% 完全兼容的 LINQ to SQL 提供程序。总有不能用的情况。因此 LINQ to SQL 是一个有漏洞的抽象。

这意味着如果您使用暴露的存储库接口,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 回答