实施存储库T。返回从EF实体映射的域模型 [英] Implementing a Repository<T> that returns a domain model mapped from an EF Entity

查看:164
本文介绍了实施存储库T。返回从EF实体映射的域模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于Jeffery Palermo的洋葱体系结构,我具有以下应用程序结构(参考链接)。因此,我的Core不依赖任何东西,我的基础结构依赖于我的Core

I have the following application structure, based on the onion architecture by Jeffery Palermo (ref link). So my Core is not dependant on anything, my Infrastructure is dependent on my Core

我的Core具有存储库合同,而我的基础结构则执行该合同。实现由我的IoC容器注入

My Core has the Repository Contract and my Infrastructure implements it. The Implementation gets Injected by my IoC Container

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

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

如果我写出具体的存储库实现(例如PersonRepository),就不会有问题,因为我也知道要投影/映射的类型。

So this wouldn't be a problem if I wrote out a concrete repository implementation (e.g a PersonRepository) because I know what type to project / map too.

示例具体的实现:

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;
       }
      ...
}

我可能要去关于这种错误的方式,所以我打开其他实现。

I might be going about this the wrong way so I open other implementations.

更新

好谢谢大家的想法和建议。 usr 提出了一个我已经忽略的很好的观点-如果我抽象我的ORM,我将失去ORM提供的所有好处。

Well thank you all for your thoughts and advice. usr made a very good point that I had overlooked- If I abstract over my ORM I will lose all benefits that the ORM provides.

我正在使用EF Database First开发。因此,我的实体和存储库的实现都在我的基础结构中。

I am using EF Database First development. So my Entities are in my infrastructure along with my repository implementations.

在基于洋葱体系结构构建应用程序时,域与此分开。

The Domain is separate to this as I am building my application based on the onion architecture.

如果我先执行代码,则似乎要做的事情是先构建域,然后使用EF代码首先将其转换为数据库。

If I was doing Code First it seems the thing to do is build your Domain first and using EF Code first translate this to a Database.

我不能先编写代码:(

I can't do code first :(

因此,在步骤中,EF团队@ Microsoft的Entity Framework DbCotnext POCO生成器。这将生成持久的无知POCO基于我的edmx文件的类

So, in steps the Entity Framework DbCotnext POCO generator from the EF team @ Microsoft. This generates persistent ignorant POCO classes based on my edmx file

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

This seems great so far, I have all the benefits of Lazy Loading and Change Tracking and even better my Domain is generated for me and Entity Framework handles the mapping internally. This has simplified my application :)

所以这不是我的体系结构的高级视图

So this is no a high level view of my architecture

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 


推荐答案

存储库模式用于为数据层提供抽象吗?对?

The repository pattern is used to provide an abstraction to the data layer? Right?

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

With that in mind, let's think about LINQ to SQL (no matter if it's through EF, nhibernate or anything else). There is no LINQ to SQL provider which is 100% fully compatible with LINQ. There are always cases which cannot be used. Hence LINQ to SQL is a leaky abstraction.

这意味着,如果您使用的存储库接口公开了 IQueryable< TDomainModel> 表达式< Func< TDb,bool>在哪里,您必须了解这些限制。因此,它不是一个完整的抽象。

That means that if you use a repository interface which exposes IQueryable<TDomainModel> or Expression<Func<TDb, bool>> where you have to be aware of those limitations. It's therefore not a complete abstraction.

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

Instead I recommend that you just provide a basic generic repository like this:

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

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

And then create root aggregate specific interfaces:

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

这意味着实现看起来像:

which means that the implementation would look like:

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

现在是100%工作的抽象,它更容易分辨存储库提供的功能。您现在必须再编写一些代码,但是以后不必再为泄漏的抽象而苦恼了。

It's now a 100% working abstraction where it's much easier to tell what functions the repository provides. You have to write a little bit more code now, but you don't have to struggle with a leaky abstraction later on.

您还可以切换到我演示的查询此处: http://blog.gauffin.org/2012/10/格里芬去耦查询/

You could also switch to queries like I demonstrate here: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/

这篇关于实施存储库T。返回从EF实体映射的域模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆