Asp.net mvc 实体框架6提供现成的存储库和UoW

Asp.net mvc 实体框架6提供现成的存储库和UoW,asp.net-mvc,entity-framework,ef-code-first,unit-of-work,repository,Asp.net Mvc,Entity Framework,Ef Code First,Unit Of Work,Repository,但是你如何使用它呢 我已经建立了一个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; } 将满足DI,并且在适用的情

但是你如何使用它呢

我已经建立了一个
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; }
将满足
DI
,并且在适用的情况下,它将通过构造函数注入上层类

该项目有一个类库和一个web项目
asp.NETMVC
。其中类库项目包含我的实体并启用了迁移

非常感谢您对这一问题的任何了解。

实体框架本身可以被视为一个存储库。它有助于处理数据,在本例中是数据库。这就是存储库所做的一切

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

许多复杂的项目使用2-3层存储库,存储库之间有web服务。演出水平较低,但你可以从其他计划中获益,如安全、弹性、音乐会分离等

您的公司可能会认为,永远不要直接从前端项目访问数据符合他们的最佳利益。它们可能会迫使您构建一个单独的web服务项目,该项目只能从本地主机访问。因此,您将在webservice项目中使用EF作为存储库。在前端,您显然需要构建另一个与web服务一起工作的存储库

这也取决于你的很多项目。如果它是一个小项目,那么在EF之上构建第二个存储库真是太过分了。但是,请再次阅读上面的内容。如今,安全性比性能更重要

为了在政治上正确,我加入了Wiktor Zychla的评论:

DbSet
是一个存储库,
DbContext
是一个工作单元。“实体框架是一个存储库”可能会导致不必要的混乱。”

我在几个项目中的EF(在其构建中固有地利用了存储库和UoW模式)之上添加了一个存储库层,我用一个利用泛型的类完成了这项工作,所以我的所有实体只需要一个文件。你可以决定是否要做,但我发现它在我的项目中很有用

我的存储库通常从我下面所示的开始,如果/当我遇到对它们的需求时,会使用更多的扩展方法(显然,我并没有展示所有的扩展方法,而是由您决定如何实现存储库)

公共类存储库:IRepository,其中T:class
{
环境保护;
受保护的DbSet DbSet{get{return Context.Set();}}
公共存储库(IDbContext context=null)
{
Context=Context??新的DbContext();
}
公共无效添加(T新记录)
{
添加(新记录);
}
公共作废更新(T记录)
{
var entry=Context.entry(记录);
附件(记录);
entry.State=EntityState.Modified;
}
删除公共作废(T记录)
{
Context.Entry(record).State=EntityState.Deleted;
删除(记录);
}
公共IQueryable Where(表达式谓词)
{
返回DbSet.Where(谓词);
}
公共布尔包含(表达式谓词)
{
返回DbSet.Count(谓词)>0;
}
公共整数计数(表达式谓词)
{
返回DbSet.Count(谓词);
}
公共整数保存()
{
返回Context.SaveChanges();
}
}
我使用存储库有两个主要原因:

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

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

  • 显然,这并不是全部,但对于这个答案来说,这应该足够了。如果你想知道更多关于这个话题的信息,我确实写了一篇博文给你


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

    EF 4/5也是存储库。人们只是在上面实现存储库模式,以防他们想要更改数据源(尽管我从未听说有人在花了大量的精力创建抽象之后真的这么做了…)看起来不错,代码解释得很好。您输入了一个小的拼写错误,而不是您输入的
    :IRepository
    (但是您被原谅了)。一个小问题是,存储库是否需要注入:
    kernel.Bind().to().InRequestScope()?我以前从未对其使用过注入,因此我无法真正告诉您这种或那种方法。为什么
    公共iqeryable Where(表达式谓词)
    而不是
    公共iqeryable查询{get;}
    ?为什么你会限制自己只进行过滤,而不允许排序/分组/分页/投影?1)这只是一个基本的例子,你可以根据需要轻松地进行调整。2) 您可以将所有这些内容放在存储库调用之后,因为LINQ的延迟执行实际上不会运行查询,直到有东西迫使它调用(因此使用
    IQueryable
    )。@IronMan84,还有一个问题,假设我为每个实体都有3个自定义逻辑的方法,这些方法只适用于每个实体本身。这不会让存储库变得“肮脏”吗
    kernel.Bind<MyDbContext>().ToSelf().InRequestScope();
    
    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();
        }
    }