具有通用存储库和工作单元的实体框架

本文关键字:单元 工作 实体 框架 存储 | 更新日期: 2023-09-27 18:02:09

我在我的一个应用程序中使用实体框架和通用存储库。我需要对功单位积分。我有点困惑,在不影响应用程序性能的情况下,使用通用存储库模式添加工作单元的最佳方法是什么。谁能帮我做这件事?

我已经添加了我的通用存储库代码和其他存储库代码如下。

通用存储库:

using System;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Threading.Tasks;
using EntityFrameworkDemo.Entity;
using EntityFrameworkDemo.Models;
using EntityFrameworkDemo.Repository.UnitOfWork;
namespace EntityFrameworkDemo.Repository
{
    public class BaseRepository<T> : IDisposable where T : BaseModel
    {
      internal EFContext db;
    public BaseRepository()
    {
        db = new EFContext();
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="BaseRepository"/> class.
    /// </summary>
    /// <param name="context">The context.</param>
    public BaseRepository(EFContext context)
    {
        db = context;
    }
    /// <summary>
    /// Gets this instance.
    /// </summary>
    /// <returns></returns>
    public IQueryable<T> GetAll()
    {
        return db.Set<T>().Where(t => !t.DeletedOn.HasValue);
    }

    /// <summary>
    /// Gets the specified identifier.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns></returns>
    public T Get(long? id)
    {
        return db.Set<T>().Find(id); ;
    }
    /// <summary>
    /// Gets the specified identifier.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns></returns>
    public Task<T> GetASync(long? id)
    {
        return db.Set<T>().FindAsync(id);
    }
    /// <summary>
    /// Inserts the specified current.
    /// </summary>
    /// <param name="current">The current.</param>
    /// <returns></returns>
    public async Task<T> Insert(T current)
    {
        db.Set<T>().Add(current);
        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbEntityValidationException e)
        {
            foreach (var eve in e.EntityValidationErrors)
            {
                Console.WriteLine("Entity of type '"{0}'" in state '"{1}'" has the following validation errors:",
                    eve.Entry.Entity.GetType().Name, eve.Entry.State);
                foreach (var ve in eve.ValidationErrors)
                {
                    Console.WriteLine("- Property: '"{0}'", Error: '"{1}'"",
                        ve.PropertyName, ve.ErrorMessage);
                }
            }
            throw;
        }
        return await db.Set<T>().FirstAsync();
    }
    /// <summary>
    /// Inserts the specified current.
    /// </summary>
    /// <param name="current">The current.</param>
    /// <returns></returns>
    public async Task Update(T current)
    {
        db.Entry<T>(current).State = System.Data.Entity.EntityState.Modified;
        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbEntityValidationException e)
        {
            foreach (var eve in e.EntityValidationErrors)
            {
                Console.WriteLine("Entity of type '"{0}'" in state '"{1}'" has the f  ollowing validation errors:",
                    eve.Entry.Entity.GetType().Name, eve.Entry.State);
                foreach (var ve in eve.ValidationErrors)
                {
                    Console.WriteLine("- Property: '"{0}'", Error: '"{1}'"",
                        ve.PropertyName, ve.ErrorMessage);
                }
            }
            throw;
        }
    }
    /// <summary>
    /// Deletes the specified identifier.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns></returns>
    public async Task Delete(long? id)
    {
        var current = await this.GetASync(id);
        if (current != null)
        {
            current.DeletedOn = DateTime.Now;
            db.Entry<T>(current).State = System.Data.Entity.EntityState.Modified;
            await db.SaveChangesAsync();
        }
    }
    /// <summary>
    /// Deletes the specified identifier permanently.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns></returns>
    public async Task DeletePermanently(long? id)
    {
        var current = await this.GetASync(id);
        if (current != null)
        {
            db.Set<T>().Remove(current);
            await db.SaveChangesAsync();
        }
    }
    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    /// <summary>
    /// Finalizes an instance of the <see cref="BaseRepository"/> class.
    /// </summary>
    ~BaseRepository()
    {
        Dispose(false);
    }
    /// <summary>
    /// Releases unmanaged and - optionally - managed resources.
    /// </summary>
    /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (db != null)
            {
                db.Dispose();
                db = null;
            }
        }
    }
}

}

Student Repository:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EntityFrameworkDemo.Models;
namespace EntityFrameworkDemo.Repository
{
    public class StudentRepository : BaseRepository<Student>
    {
    public StudentRepository()
        : base()
    { }
    }
}

控制器:

 public class HomeController : Controller
{
    private StudentRepository studentRepo = new StudentRepository();
    public async Task<ActionResult> Index()
    {
        var test = studentRepo.GetAll();
        return View();
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            studentRepo.Dispose();
        }
        base.Dispose(disposing);
    }
}

具有通用存储库和工作单元的实体框架

您可能想知道实体框架上下文是工作单元模式的实现(当您执行context.SaveChanges()时,您执行的是一个工作单元)。所以我很确定,在90%的情况下,没有必要在它上面做额外的实现,除非你想从具体的数据源/数据访问抽象你的数据层。我必须说,如果您不需要这种抽象,那么您根本不需要存储库模式。

不管怎样,这个问题太宽泛了。你应该描述为什么你想在你的应用程序中使用存储库模式的意图。

使用通用存储库有利有弊。一个在接口中有IQueryable的存储库显示了底层技术,这意味着替换这个底层技术变得更加困难,因为IQueryable并不那么容易实现。因此,有人说通用存储库不提供任何抽象,您还不如在没有通用存储库的情况下立即使用EF。(如果你不能用不同的实现替换一个层,那么你和那个实现耦合得太紧了)。您会发现也有人支持使用通用存储库。存储库可以有接口,接口是可模拟的,您的代码将很容易进行单元测试。使用或不使用通用存储库在很大程度上是基于个人意见的。既然你正在使用一个,我想你有很好的理由需要一个

但是我不认为你应该从头开始编写你自己的通用库/unitofwork。最好是基于一些已经免费提供并提供良好功能的实现,例如:

https://genericunitofworkandrepositories.codeplex.com/

它提供了你需要的,并提供了强大的查询功能,还支持async和await。

工作单元本身对性能没有威胁,因为它只是EF上下文的包装,而EF实际上已经是一个工作单元了。性能问题存在于您执行的查询中。这些需要逐一求值。还有很多事情要考虑。

- lazy loading
- eager loading
- explicit loading

你可能想读一下我对过度使用include的问题的回答:

优化实体框架查询,避免延迟加载。

性能是一个大话题。没有简单的答案,也绝对没有一个适合所有EF性能问题的答案。