【问题标题】:Entity framework 6 providing repositories and UoW out of the box实体框架 6 提供开箱即用的存储库和 UoW
【发布时间】:2014-12-15 20:12:41
【问题描述】:

但是你如何使用它呢?

我设置了一个Code First 项目,并尝试使用这个新的 EF6 做一些事情。阅读至少 2 岁关于 EF4/5 的各种帖子/博客。但是关于 EF6 什么都没有。

假设我有这些实体:

public DbSet<Person> Persons { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Invoice> Invoices { get; set; }

我还需要为每个实体创建存储库吗?或者class 是否足以使用一些方法来进行除 CRUD 之外的一些自定义计算?

我知道这一行:

kernel.Bind<MyDbContext>().ToSelf().InRequestScope();

对于DI 就足够了,并且它将通过构造函数注入到适用的上层类。

该项目有一个类库和一个网络项目asp.net-mvc。类库项目包含我的实体并启用了Migrations

非常感谢您对此事的任何了解。

【问题讨论】:

  • EF 4/5 也是存储库。人们只是在上面实现存储库模式,以防他们想要更改数据源(尽管我从未听说有人在花费大量工作创建该抽象之后真正这样做......)

标签: asp.net-mvc entity-framework ef-code-first unit-of-work repository


【解决方案1】:

我在几个项目中在 EF 之上添加了一个 Repository 层(它在其构造中固有地利用了 Repository 和 UoW 模式),并且我已经通过一个使用泛型的类来做到这一点,因此我只需要我所有实体的一个文件。您可以决定是否要这样做,但我发现它在我的项目中很有用。

我的存储库通常像我在下面显示的那样开始,如果/当我遇到对它们的需求时,会跟进更多扩展方法(显然我没有显示所有它们,这由你决定如何实现您的存储库)。

public class Repository<T> : IRepository<T> where T : class
{
    protected IDbContext Context;
    protected DbSet<T> DbSet { get { return Context.Set<T>(); } }

    public Repository(IDbContext context = null)
    {
        Context = context ?? new DbContext();
    }

    public void Add(T newRecord)
    {
        DbSet.Add(newRecord);
    }

    public void Update(T record)
    {
        var entry = Context.Entry(record);
        DbSet.Attach(record);
        entry.State = EntityState.Modified;
    }

    public void Remove(T record)
    {
        Context.Entry(record).State = EntityState.Deleted;
        DbSet.Remove(record);
    }

    public IQueryable<T> Where(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public bool Contains(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Count(predicate) > 0;
    }

    public int Count(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Count(predicate);
    }

    public int Save()
    {
        return Context.SaveChanges();
    }
}

我使用存储库有两个主要原因:

  1. 单元测试。使用这种模式可以让我伪造底层数据,而不必在我的数据库中有坏数据。我需要做的只是创建另一个IRepository 的实现,它使用内存中的列表作为其数据源,并且我已准备好让我的页面查询该存储库。

  2. 可扩展性。很多次我将一些方法放入我的存储库,因为我发现自己不断地在控制器中对查询执行相同的逻辑。这非常有用,特别是因为您的客户端代码不需要知道它是如何做的,只需知道它正在做(如果您需要更改一个文件与多个文件的逻辑,这将更容易) )。

显然,这还不是全部,但对于这个答案来说应该足够了。如果您想了解有关此主题的更多信息,我确实写了一篇关于您的博客文章 can find here

无论你决定做什么,祝你好运。

【讨论】:

  • 看起来不错,用代码解释得很好。你打了一个小错字,而不是: IRepository 你做了: Repository (但你被原谅了)。想了一个小问题,那个存储库,是否需要注入:kernel.Bind&lt;IRepository&gt;().To&lt;Repository&gt;().InRequestScope();?
  • 我以前从来没有用过注射,所以我真的不能告诉你任何一种方式。
  • 为什么是public IQueryable&lt;T&gt; Where(Expression&lt;Func&lt;T, bool&gt;&gt; predicate) 而不是public IQueryable&lt;T&gt; Query { get; }?你为什么要限制自己只过滤而不让排序/分组/分页/投影?
  • 1) 这只是一个基本示例,您可以根据需要轻松调整。 2) 你可以把所有这些东西放在 Repository 调用之后,因为 LINQ 的延迟执行实际上不会运行查询,直到有东西强制它调用(因此使用IQueryable)。
  • @IronMan84,还有一个问题,假设我对每个实体都有 3 个方法,这些方法具有仅适用于每个实体本身的自定义逻辑。这不会使存储库有点“脏”吗?
【解决方案2】:

Entity Framework 本身可以被认为是一个Repository。它有助于处理数据,在这种情况下是数据库。这就是存储库所做的一切。

如果您想在 EF 提供的基础上构建另一个 Repository,这完全取决于您 - 或您的业务规则。

许多复杂的项目使用 2-3 层存储库,其中包含 Web 服务。性能较低,但您在其他计划(如安全性、弹性、音乐会分离等)上有所收获。

您的公司可能会决定从不直接从前端项目访问数据符合他们的最大利益。他们可能会强迫您构建单独的网络服务项目,该项目只能从本地主机访问。因此,您最终将在 web 服务项目中将 EF 作为 Repository。在前端,您显然需要构建另一个 Repository 它将与 Web 服务一起使用。

这也很大程度上取决于您的项目。如果它是一个小项目,那么在 EF 之上构建第二个 Repository 确实有点过头了。但话又说回来,请阅读上文。如今,安全性比性能更重要。

为了政治正确,我将 Wiktor Zychla 的评论包括在内:
DbSet 是一个存储库,DbContext 是一个工作单元。“Entity Framework 是一个存储库”可能会导致不必要的混淆。”

【讨论】:

  • 我确实将关注点分离作为这个项目的设计。只有 2 层,这意味着我确实需要某种存储库来获取数据等。
  • 第一个分离应该是在一个单独的 Web 服务项目中托管与数据库一起使用的 Repo。在前端项目中,您显然需要另一个 Repo,这将使您能够使用 WS。在大多数情况下,这应该足够了。
  • @Mihai-AndreiDinculescu:DbSet 是一个存储库,DbContext 是一个工作单元。 “Entity Framework is a Repository”可能会导致不必要的混淆。
猜你喜欢
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 2011-06-10
  • 2015-01-30
  • 2010-12-11
相关资源
最近更新 更多