zoukankan      html  css  js  c++  java
  • ASP.NET MVC4+EF系列之六仓储实现 IRepository 和 Repository

    名词介绍:首先我们必须了解一点领域驱动(DDD)相关知识,至少要对一些名词熟悉,我上传的源代码的注释包含了很多这些名词。例如仓储仓储上下文,仓储根领域对象,以及什么领域对象可以考虑作为仓储根。这里我就按我的理解做个粗浅的介绍。不当之处请原谅。比较DDD不是一朝一夕能领悟的东西,需要理论加实践的不断磨合,我这里只是简单的DDD。

      1.领域对象:就是我们业务中的一个个对象。我想这不用多加解释了。

      2.仓储根:就是能被直接操作到数据库的领域对象,它是领域对象的子集。业务当中的所有操作都是对仓储根的操作。也只有仓储根能被放进仓储,让后被固化到数据库。在不同的业务中仓储根是不同的,利于在订单中订单对象肯定就是仓储根,但是订单地址就不是,订单地址只是作为订单的属性而存在。我们框架中通过这个TAggregateRoot借口去

      3.仓储:其实就是领域对象存放的地方。每一个领域对象都有自己的仓储。这里面存储了很多同一类型的对象

      4.仓储上下文:不通仓储存放的地方,对不通仓储根的仓储进行管理。

    更多的名词我就不一一介绍,我只介绍我用的比较多的。更多领域驱动相关,推荐大家网上学习了解下

    一.IRepository 和 Repositor概述

      Repository顾名思义就是仓储,Repository继承了IRepository接口,并且实现了一套通用的操作仓储根的方法,通过这些方法我们可以很灵活的操作数据库。Repository只是基础的仓储。至于具体的通过EF还是NH去实现数据的固化和查询。我们主要继承Repository这个类就行了。Repository是一个抽象类。只能被继承。让后去实现各种具体的仓储,是用EF还是用NH操作数据那就取决于我们了。IRepository为仓储提供了一套标准。我么这里选择了EF,这种后面详述。

      1.IRepository基本仓储标准

      

     1 /*****************************************************
     2  * 作者:egojit
     3  * 日期:2012-7-13
     4  * 描述:仓储接口
     5  * ***************************************************/
     6 using System;
     7 using System.Collections.Generic;
     8 using System.Linq.Expressions;
     9 using EgojitFramework.Domain.Specifications;
    10 
    11 
    12 namespace EgojitFramework.Domain.Repositories
    13 {
    14     /// <summary>
    15     /// 仓储接口
    16     /// </summary>
    17     /// <typeparam name="TAggregateRoot">仓储根类型</typeparam>
    18     public interface IRepository<TAggregateRoot>
    19         where TAggregateRoot : class, IAggregateRoot
    20     {
    21         /// <summary>
    22         ///获取仓储上下文实例
    23         /// </summary>
    24         IRepositoryContext Context { get; }
    25         /// <summary>
    26         /// 添加一个仓储根到仓储中
    27         /// </summary>
    28         /// <param name="aggregateRoot">仓储根.</param>
    29         void Add(TAggregateRoot aggregateRoot);
    30         /// <summary>
    31         /// 通过Key从仓储中获取仓储根实例
    32         /// </summary>
    33         /// <param name="key">key.</param>
    34         /// <returns>仓储根实例</returns>
    35         TAggregateRoot GetByKey(Guid key);
    36         /// <summary>
    37         /// 从仓储中获取所有的仓储根实例
    38         /// </summary>
    39         /// <returns>仓储根实例列表</returns>
    40         IEnumerable<TAggregateRoot> GetAll();
    41         /// <summary>
    42         /// 分页从仓储中获取所有的仓储根实例
    43         /// </summary>
    44         /// <param name="pageNumber">页号</param>
    45         /// <param name="pageSize">每页的数量</param>
    46         /// <returns>指定页的仓储根列表</returns>
    47         IEnumerable<TAggregateRoot> GetAll(int pageNumber, int pageSize);
    48         /// <summary>
    49         /// 从仓储中获取所有的仓储根实例并且排序
    50         /// </summary>
    51         /// <param name="sortPredicate">The sort predicate which is used for sorting.</param>
    52         /// <param name="sortOrder">The <see cref="Apworks.SortOrder"/> enumeration which specifies the sort order.</param>
    53         /// <returns>All the aggregate roots got from the repository, with the aggregate roots being sorted by
    54         /// using the provided sort predicate and the sort order.</returns>
    55         IEnumerable<TAggregateRoot> GetAll(Expression<Func<TAggregateRoot, dynamic>> sortPredicate, SortOrder sortOrder);
    56         /// <summary>
    57         /// 分页从仓储中获取所有的仓储根实例并且排序
    58         /// </summary>
    59         /// <param name="sortPredicate">排序条件</param>
    60         /// <param name="sortOrder">排序方式</param>
    61         /// <param name="pageNumber">页号</param>
    62         /// <param name="pageSize">每页数量</param>
    63         /// <returns>排序后的仓储根列表</returns>
    64         IEnumerable<TAggregateRoot> GetAll(Expression<Func<TAggregateRoot, dynamic>> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize);
    65 }
    66 }

    当然这个接口中远不止这么多代码。更多请参照源码。从

     /// <summary>
        /// 仓储接口
        /// </summary>
        /// <typeparam name="TAggregateRoot">仓储根类型</typeparam>
        public interface IRepository<TAggregateRoot>
            where TAggregateRoot : class, IAggregateRoot

    这行代码我们很容易看出来IRepository类中的操作的对象都是基础自TAggregateRoot接口的仓储根,这就很好的限制了普通实体的数据库操作。

       2.继承自IRepository接口的Repository仓储类

      部分代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using EgojitFramework.Domain.Specifications;
    using System.Linq.Expressions;
    /*****************************************************
     * 作者:egojit
     * 日期:2012-7-13
     * 描述:仓储抽象类
     * ***************************************************/
    namespace EgojitFramework.Domain.Repositories
    {
        /// <summary>
        /// 仓储基础类
        /// </summary>
        /// <typeparam name="TAggregateRoot">The type of the aggregate root on which the repository operations
        /// should be performed.</typeparam>
        public abstract class Repository<TAggregateRoot> : IRepository<TAggregateRoot>
            where TAggregateRoot : class, IAggregateRoot
        {
            #region 私有字段
            private readonly IRepositoryContext context;
            #endregion
    
            #region 属性
            /// <summary>
            /// 仓储上下文的一个实例
            /// </summary>
            /// <param name="context">被这个仓储使用的仓储上下文</param>
            public Repository(IRepositoryContext context)
            {
                this.context = context;
            }
            #endregion
    
            #region 私有方法
            /// <summary>
            /// 添加一个仓储根到仓储
            /// </summary>
            /// <param name="aggregateRoot">被添加的仓储根</param>
            protected abstract void DoAdd(TAggregateRoot aggregateRoot);
            /// <summary>
            /// 通过Key在这个仓储中获取仓储根
            /// </summary>
            /// <param name="key">Key</param>
            /// <returns>仓储实例</returns>
            protected abstract TAggregateRoot DoGetByKey(Guid key);
    。。。。。。此次省去更多代码
    }
    }

    通过代码我们很容易知道它操作的也是仓储根,并且继承了IRepository接口,而且它是抽象的,必须被继承去实现,这样我们就为基于EF或者是NH或者其它实现的仓储提供了一种很容易的途径,只要在他的子类中去重现其中的方法就行了。我们看到通过构造函数将仓储上下文带到了这个类中。

    这节就介绍这个基本仓储,下个节。将介绍仓储中的事务管理。(次阶段源代码下载)

    版权:归博客园和egojit共同所有,转载请标明出处

  • 相关阅读:
    集中式(SVN)和分布式(Git)版本控制系统的简单比较
    Mac 提示安装包已损坏
    React 获取 url 参数 —— this.props.match
    编写一个 Chrome 浏览器扩展程序
    webpack 配置学习笔记
    Python 进阶学习笔记
    Python 入门学习笔记
    (转)Unity3d各种坑
    unity3d 网页游戏客户端工程构建方案
    (转)在Unity3D的网络游戏中实现资源动态加载
  • 原文地址:https://www.cnblogs.com/egojit/p/3070913.html
Copyright © 2011-2022 走看看