我有以下应用程序结构,基于 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/