iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >ASP.NetCore基于EF6、Unitwork、Autofac实现Repository模式
  • 213
分享到

ASP.NetCore基于EF6、Unitwork、Autofac实现Repository模式

2024-04-02 19:04:59 213人浏览 泡泡鱼
摘要

一、实现的思路和结构图 Repository的共同性 有一些公共的方法(增删改查), 这些方法无关于Repository操作的是哪个实体类,可以把这些方法定义成接口IReposito

一、实现的思路和结构图

  • Repository的共同性

有一些公共的方法(增删改查), 这些方法无关于Repository操作的是哪个实体类,可以把这些方法定义成接口IRepository,然后有个基类BaseRepository实现该接口的方法。常见的方法,比如Find, Filter, Delete, Create等

  • Repository的差异性

每个Repository类又会有一些差异性,应当允许它们能够继承BaseRepository之外,还能够再扩展自己的一些方法。所以每个类都可以再定义一个自己特有的接口,定义一些属于自己Repository的方法。

  • Repository的协同性

不同的Repository可能需要协同,Repository对数据的修改,需要在统一的保存.
最终实现的类结构图如下:

类结构图

二、Repository设计具体的实现代码

IRepository接口定义了Repository共有的方法, BaseRepository实现了这些接口的方法。其它的Repository类再集成BaseRepository方法,就天然的得到了对数据操作的基本方法。

  • IRepository代码
    public interface IRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// Gets all objects from database
        /// </summary>
        /// <returns></returns>
        IQueryable<TEntity> All();

        /// <summary>
        /// Gets objects from database by filter.
        /// </summary>
        /// <param name="predicate">Specified a filter</param>
        /// <returns></returns>
        IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// Gets objects from database with filtering and paging.
        /// </summary>
        /// <param name="filter">Specified a filter</param>
        /// <param name="total">Returns the total records count of the filter.</param>
        /// <param name="index">Specified the page index.</param>
        /// <param name="size">Specified the page size</param>
        /// <returns></returns>
        IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> filter, out int total, int index = 0, int size = 50);

        /// <summary>
        /// Gets the object(s) is exists in database by specified filter.
        /// </summary>
        /// <param name="predicate">Specified the filter expression</param>
        /// <returns></returns>
        bool Contains(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// Find object by keys.
        /// </summary>
        /// <param name="keys">Specified the search keys.</param>
        /// <returns></returns>
        TEntity Find(params object[] keys);

        /// <summary>
        /// Find object by specified expression.
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        TEntity Find(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// Create a new object to database.
        /// </summary>
        /// <param name="t">Specified a new object to create.</param>
        /// <returns></returns>
        void Create(TEntity t);

        /// <summary>
        /// Delete the object from database.
        /// </summary>
        /// <param name="t">Specified a existing object to delete.</param>
        void Delete(TEntity t);

        /// <summary>
        /// Delete objects from database by specified filter expression.
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        int Delete(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// Update object changes and save to database.
        /// </summary>
        /// <param name="t">Specified the object to save.</param>
        /// <returns></returns>
        void Update(TEntity t);

        /// <summary>
        /// Select Single Item by specified expression.
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        TEntity FirstOrDefault(Expression<Func<TEntity, bool>> expression);
    }
  • BaseRepository代码
    public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        protected readonly DbContext Context;

        public BaseRepository(DbContext context)
        {
            Context = context;
        }

        /// <summary>
        /// Gets all objects from database
        /// </summary>
        /// <returns></returns>
        public IQueryable<TEntity> All()
        {
            return Context.Set<TEntity>().AsQueryable();
        }

        /// <summary>
        /// Gets objects from database by filter.
        /// </summary>
        /// <param name="predicate">Specified a filter</param>
        /// <returns></returns>
        public virtual IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate)
        {
            return Context.Set<TEntity>().Where<TEntity>(predicate).AsQueryable<TEntity>();
        }

        /// <summary>
        /// Gets objects from database with filtering and paging.
        /// </summary>
        /// <param name="filter">Specified a filter</param>
        /// <param name="total">Returns the total records count of the filter.</param>
        /// <param name="index">Specified the page index.</param>
        /// <param name="size">Specified the page size</param>
        /// <returns></returns>
        public virtual IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> filter, out int total, int index = 0,
            int size = 50)
        {
            var skipCount = index * size;
            var resetSet = filter != null
                ? Context.Set<TEntity>().Where<TEntity>(filter).AsQueryable()
                : Context.Set<TEntity>().AsQueryable();
            resetSet = skipCount == 0 ? resetSet.Take(size) : resetSet.Skip(skipCount).Take(size);
            total = resetSet.Count();
            return resetSet.AsQueryable();
        }

        /// <summary>
        /// Gets the object(s) is exists in database by specified filter.
        /// </summary>
        /// <param name="predicate">Specified the filter expression</param>
        /// <returns></returns>
        public bool Contains(Expression<Func<TEntity, bool>> predicate)
        {
            return Context.Set<TEntity>().Any(predicate);
        }

        /// <summary>
        /// Find object by keys.
        /// </summary>
        /// <param name="keys">Specified the search keys.</param>
        /// <returns></returns>
        public virtual TEntity Find(params object[] keys)
        {
            return Context.Set<TEntity>().Find(keys);
        }

        /// <summary>
        /// Find object by specified expression.
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual TEntity Find(Expression<Func<TEntity, bool>> predicate)
        {
            return Context.Set<TEntity>().FirstOrDefault<TEntity>(predicate);
        }

        /// <summary>
        /// Create a new object to database.
        /// </summary>
        /// <param name="t">Specified a new object to create.</param>
        /// <returns></returns>
        public virtual void Create(TEntity t)
        {
            Context.Set<TEntity>().Add(t);
        }

        /// <summary>
        /// Delete the object from database.
        /// </summary>
        /// <param name="t">Specified a existing object to delete.</param>
        public virtual void Delete(TEntity t)
        {
            Context.Set<TEntity>().Remove(t);
        }

        /// <summary>
        /// Delete objects from database by specified filter expression.
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
        {
            var objects = Filter(predicate);
            foreach (var obj in objects)
                Context.Set<TEntity>().Remove(obj);
            return Context.SaveChanges();
        }

        /// <summary>
        /// Update object changes and save to database.
        /// </summary>
        /// <param name="t">Specified the object to save.</param>
        /// <returns></returns>
        public virtual void Update(TEntity t)
        {
            try
            {
                var entry = Context.Entry(t);
                Context.Set<TEntity>().Attach(t);
                entry.State = EntityState.Modified;
            }
            catch (OptimisticConcurrencyException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Select Single Item by specified expression.
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> expression)
        {
            return All().FirstOrDefault(expression);
        }
    }

IUnitOfWork接口定义了方法获取特定的Repository, 执行存储过程, SaveChange方法提交修改,统一更新数据。

  • IUnitOfWork接口代码:
    public interface IUnitOfWork : IDisposable
    {
        DbContext DbContext { get; }
        TRepository GetRepository<TRepository>() where TRepository : class;
        void ExecuteProcedure(string procedureCommand, params object[] sqlParams);
        void ExecuteSql(string sql);
        List<T> SqlQuery<T>(string sql);
        void SaveChanges();
    }

UnitOfWork代码, 代码中使用到了Autofac中的IComponentContext来获取Repository实例

    public class UnitOfWork : IUnitOfWork
    {
        private readonly IComponentContext _componentContext;
        protected readonly DbContext Context;

        public UnitOfWork(DbContext context, IComponentContext componentContext)
        {
            Context = context;
            _componentContext = componentContext;
        }

        public DbContext DbContext => Context;

        public TRepository GetRepository<TRepository>() where TRepository : class
        {
            return _componentContext.Resolve<TRepository>();
        }

        public void ExecuteProcedure(string procedureCommand, params object[] sqlParams)
        {
            Context.Database.ExecuteSqlCommand(procedureCommand, sqlParams);
        }

        public void ExecuteSql(string sql)
        {
            Context.Database.ExecuteSqlCommand(sql);
        }

        public List<T> SqlQuery<T>(string sql)
        {
            return Context.Database.SqlQuery<T>(sql).ToList();
        }

        public void SaveChanges()
        {
            try
            {
                Context.SaveChanges();
            }
            catch (InvalidOperationException ex)
            {
                if (!ex.Message.Contains("The changes to the database were committed successfully"))
                {
                    throw;
                }
            }
        }

        public void Dispose()
        {
            Context?.Dispose();
        }
    }

三、Repository设计的具体的使用

这里我们定义一个IStudentRepository接口, 包含了方法GetAllStudents(), 同时继承于IRepository<Student>接口

public interface IStudentRepository : IRepository<Student>
{
    IEnumerable<dynamic> GetAllStudents();
}

接着定义StudentRepository类来实现这个接口

public class StudentRepository : BaseRepository<Student>, IStudentRepository
{
    private readonly SchoolContext _context;

    public StudentRepository(SchoolContext context)
        : base(context)
    {
        _context = context;
    }

    public IEnumerable<dynamic> GetAllStudents()
    {
        return _context.Students;
    }
}
  • Application_Start方法中使用Autofac注册Repository的代码如下:
    var builder = new ContainerBuilder();

    //reGISter controllers
    builder.RegisterControllers(typeof(mvcApplication).Assembly);

    //register repository
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();

    //add the Entity Framework context to make sure only one context per request
    builder.RegisterType<SchoolContext>().InstancePerRequest();
    builder.Register(c => c.Resolve<SchoolContext>()).As<DbContext>().InstancePerRequest();

    var container = builder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
  • 在控制器中注入使用Repository的代码如下:
private readonly IUnitOfWork _repositoryCenter;

private readonly IStudentRepository _studentRepository;

public HomeController(IUnitOfWork repositoryCenter)
{
    _repositoryCenter = repositoryCenter;
    _studentRepository = _repositoryCenter.GetRepository<IStudentRepository>();
}

public ActionResult Index(Student sessionStudent)
{
    var students = _studentRepository.GetAllStudents();

    // 同时你也可以使用定义于IRepository<Student>中的方法, 比如:

    _studentRepository.Delete(students.First());
    _repositoryCenter.SaveChanges();

    ...

    return View(students);
}

四、思路总结

上面的设计,把Repository的通用代码剥离到父类中,同时又允许每个Repository扩展自己的方法,达到了比较理想的状态。

只是现在的设计和Autofac耦合了,但是如果想继续剥离Autofac直接使用 _repositoryCenter.GetRepository<IStudentRepository>(); 的方式获取IStudentRepository的实例就很困难了。

五、案例源码

源代码仓库 AutoFacMvc

到此这篇关于ASP.net core基于EF6、Unitwork、Autofac实现Repository模式的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: ASP.NetCore基于EF6、Unitwork、Autofac实现Repository模式

本文链接: https://www.lsjlt.com/news/139391.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • ASP.NetCore基于EF6、Unitwork、Autofac实现Repository模式
    一、实现的思路和结构图 Repository的共同性 有一些公共的方法(增删改查), 这些方法无关于Repository操作的是哪个实体类,可以把这些方法定义成接口IReposito...
    99+
    2024-04-02
  • 如何实现Repository模式
    这篇文章主要介绍“如何实现Repository模式”,在日常操作中,相信很多人在如何实现Repository模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何实现Repository模式”的疑惑有所帮助!...
    99+
    2023-06-22
  • Laravel中如何实现Repository设计模式
    本文小编为大家详细介绍“Laravel中如何实现Repository设计模式”,内容详细,步骤清晰,细节处理妥当,希望这篇“Laravel中如何实现Repository设计模式”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习...
    99+
    2023-07-04
  • java基于NIO实现群聊模式
    本文实例为大家分享了java基于NIO实现群聊模式的具体代码,供大家参考,具体内容如下 Client package com.qst.chat; import java.io....
    99+
    2024-04-02
  • .NET 6开发TodoList应用之实现Repository模式
    目录需求目标原理和思路实现通用Repository实现引入使用验证总结参考资料需求 经常写CRUD程序的小伙伴们可能都经历过定义很多Repository接口,分别做对应的实现,依赖注...
    99+
    2024-04-02
  • 基于Java利用static实现单例模式
    目录一、之前旧的写法二、static代码块的效果三、单例的另一种写法四、总结一、之前旧的写法 class Singleton{     private Singleton() {} ...
    99+
    2024-04-02
  • java基于NIO如何实现群聊模式
    这篇文章将为大家详细讲解有关java基于NIO如何实现群聊模式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体内容如下Clientpackage com.qst.chat;import&nbs...
    99+
    2023-06-21
  • 基于Java实现Actor模型
    目录ActorNodeActorSystemActorSystem初始化创建Actor发送消息休眠Actor定时器小结Actor模型是一种常见的并发模型,与最常见的并发模型&mdas...
    99+
    2023-05-19
    Java实现Actor模型 Java Actor模型 Java Actor
  • C#实现基于任务的异步编程模式
    目录一.延续任务二.同步上下文三.使用多个异步方法1.按顺序调用异步方法2.使用组合器四.转换异步模式五.错误处理1.异步方法的异常处理2.多个异步方法的异常处理3.使用Aggreg...
    99+
    2024-04-02
  • 如何进行kubernetes scheduler基于map/reduce模式实现
    如何进行kubernetes scheduler基于map/reduce模式实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。优选阶段通过分map/reduce...
    99+
    2023-06-19
  • 基于vue3和element-plus的暗黑模式怎么实现
    本篇内容介绍了“基于vue3和element-plus的暗黑模式怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、基本使用因为是通过...
    99+
    2023-07-04
  • ASP.NETCore模仿中间件方式实现列表过滤功能
    我们的很多功能当中都会遇到对版本进行过滤的场合,例如你可能需要对列表中的数据的时间进行过滤、版本过滤、渠道以及地区信息进行过滤。 原本的做法:设计很多个过滤方法,通过枚举的方式组合,...
    99+
    2024-04-02
  • 基于Dojo如何实现MVC模式下的Ajax应用
    基于Dojo如何实现MVC模式下的Ajax应用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。本人要实现项目中的一项应用是控制服...
    99+
    2024-04-02
  • 基于vue3和element-plus的暗黑模式如何实现
    这篇文章主要介绍“基于vue3和element-plus的暗黑模式如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于vue3和element-plus的暗黑模式如何实现”文章能帮助大家解决问...
    99+
    2023-07-06
  • 基于EEE3模式的3DES算法加密和解密实现
    3DES(Triple Data Encryption Standard)算法是对DES算法的增强版本,它使用三次DES算法来实现更...
    99+
    2023-09-13
    EEE3
  • python基于concurrent模块实现多线程
    目录引言       操作多线程/多进程 1、创建线程池 2、submit 3、map 4、wait 5、异常处理 引言&...
    99+
    2024-04-02
  • C#基于自定义事件EventArgs实现发布订阅模式
    一、事件参数 //事件参数 class CustomEventArgs:EventArgs { public CustomEventArgs(...
    99+
    2024-04-02
  • 基于jQuery模拟实现淘宝购物车模块
    这是网页版淘宝中购物车的页面 注意给checkbox添加事件就是用change() 给button添加事件就是用click() 1、每次点击+号,根据文本框的值乘以当前商品的价格就...
    99+
    2024-04-02
  • PythonOpenCV实现基于模板的图像拼接
    之前基于特征点的图像拼接如果是多张图,每次计算变换矩阵,都有误差,最后可以图像拼完就变形很大,基于模板的方法可以很好的解决这一问题。 import cv2 import nump...
    99+
    2024-04-02
  • ASP.NET基于事件的异步模式与异步Action怎么实现
    本篇内容主要讲解“ASP.NET基于事件的异步模式与异步Action怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ASP.NET基于事件的异步模式与异步Action怎么实现”吧!尽管在A...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作