c# - 实现返回从 EF 实体映射的域模型的 Repository<T>

标签 c# entity-framework repository-pattern

我有以下应用程序结构,基于 Jeffery Palermo 的洋葱架构 (ref link) 。所以我的核心不依赖于任何东西,我的基础设施依赖于我的核心

我的核心有存储库合约,我的基础设施实现了它。该实现由我的 IoC 容器注入(inject)

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 First 将其转换为数据库。

我不能先写代码:(

因此,来自 EF 团队 @ Microsoft 的 Entity Framework DbCotnext POCO 生成器正在逐步开发。这会根据我的 edmx 文件生成持久的无知 POCO 类

到目前为止,这看起来很棒,我拥有延迟加载和更改跟踪的所有好处,甚至更好的是,我的域是为我生成的, Entity Framework 在内部处理映射。这简化了我的应用程序:)

所以这不是我的架构的高级 View

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 

最佳答案

存储库模式用于为数据层提供抽象?正确的?

考虑到这一点,让我们考虑一下 LINQ to SQL(无论是通过 EF、nhibernate 还是其他方式)。没有 LINQ to SQL 提供程序与 LINQ 100% 完全兼容。总有无法使用的情况。因此 LINQ to SQL 是一个有漏洞的抽象。

这意味着如果您使用公开 IQueryable<TDomainModel> 的存储库接口(interface)或Expression<Func<TDb, bool>> where你必须意识到这些限制。因此,它不是一个完整的抽象。

相反,我建议您只提供一个基本的通用存储库,如下所示:

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

然后创建根聚合特定接口(interface):

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/

关于c# - 实现返回从 EF 实体映射的域模型的 Repository<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13387858/

相关文章:

c# - 使用 Min 或 Max 时如何处理 LINQ 中的空值?

c# - 自动生成 ID GUID 数据类型 Entity Framework

entity-framework - Entity Framework 包括集合/引用,其中

c# - 如何使用存储库模式在 EF Core 3.0 中进行并行异步查询?

c# - 将实体保存到数据库——我的 Save 方法应该返回保存的实体吗?

c# - 在数据库中查找 MAX() 并加 1

entity-framework - 使用 Repository/UoW/DI 抽象 EntityFramework.dll 引用

c# - 一个 DbContext Instance 跨越多个 Repositories

c# - 无法使用 MSMQ 让 MassTransit 在 IIS Express 上工作

c# - 专门处理 0 值的 Get 方法