这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

前言

我们进行linq to sql和ef时代后,底层的实现基本使用的是repository模块,即仓储模式,事实上就是把ORM实体的最基本操作进行封闭,对外层不公开操作实现的细节。

面向接口的编程

一个规定,多个实现,这可能是接口给我们带来的最直观的印象了,比如一个仓储在定义后,你可以用linq to sql实现它,也可以用ef去实现它,再或者使用ado.net去实现它,但它对外暴露的永远是稳定的接口,这里我们称为IRepository。

仓储接口是否应该设计成基础操作接口和扩展操作接口

这是今天说的重点,我们把仓储的最基本操作提炼出来,放到IRepository接口里,它叫做基本操作接口;将集合操作及其它附加操作放在IExtensionRepository接口里,我们称它为扩展操作接口;而我们再建立一个完成功能的接口ICompleteRepository,它会集成前两个接口,当调用方要求使用IRepository和IExtensionRepository的功能时,我们必须使用ICompleteRepository去声明对象,而简单的操作我们只需要使用IRepository去声明对象即可。

 IRepository接口我们可以这样定义:

  public interface IRepository<TEntity>
           where TEntity : class
    {
        /// <summary>
        /// 添加实体并提交到数据服务器
        /// </summary>
        /// <param name="item">Item to add to repository</param>
        void Insert(TEntity item);

        /// <summary>
        /// 移除实体并提交到数据服务器
        /// 如果表存在约束,需要先删除子表信息
        /// </summary>
        /// <param name="item">Item to delete</param>
        void Delete(TEntity item);

        /// <summary>
        /// 修改实体并提交到数据服务器
        /// </summary>
        /// <param name="item"></param>
        void Update(TEntity item);

        /// <summary>
        /// Get all elements of type {T} in repository
        /// </summary>
        /// <returns>List of selected elements</returns>
        IQueryable<TEntity> GetModel();

        /// <summary>
        /// 根据主键得到实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity Find(params object[] id);
    }

对于扩展的功能接口,我们可以这样去定义:

/// <summary>
    /// 扩展的Repository操作规范
    /// </summary>
    public interface IExtensionRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// 添加集合
        /// </summary>
        /// <param name="item"></param>
        void Insert(IEnumerable<TEntity> item);

        /// <summary>
        /// 修改集合
        /// </summary>
        /// <param name="item"></param>
        void Update(IEnumerable<TEntity> item);

        /// <summary>
        /// 删除集合
        /// </summary>
        /// <param name="item"></param>
        void Delete(IEnumerable<TEntity> item);

        /// <summary>
        /// 扩展更新方法,只对EF支持
        /// </summary>
        /// <param name="entity"></param>
        void Update(System.Linq.Expressions.Expression<Action<TEntity>> entity);

        /// <summary>
        /// 根据指定规约得到延时结果集
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        IQueryable<TEntity> GetModel(Commons.Entity.Specification.ISpecification<TEntity> specification);

        /// <summary>
        ///  根据指定lambda得到延时结果集
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        IQueryable<TEntity> GetModel(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        ///  根据指定规约得到实体
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        TEntity Find(Commons.Entity.Specification.ISpecification<TEntity> specification);

        /// <summary>
        /// 根据指定lambda得到实体
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        TEntity Find(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate);

    }

而为了使业务层即有IRepository而且还有IExtensionRepository接口的功能,我们将建立一个完整操作的接口,它由仓储实现基类去集成,在业务层,可以声明

这个完整的仓储接口:

    /// <summary>
    /// 完整的数据操作接口
    /// 完整的接口中,包括两个事件
    /// </summary>
    public interface ICompleteRepository<T> :
        IRepository<T>,
        IExtensionRepository<T>
         where T : class
    {
        /// <summary>
        /// Occurs after data saved
        /// </summary>
        event EventHandler<SavedEventArgs> AfterSaved;

        /// <summary>
        /// Occurs before data saved
        /// </summary>
        event EventHandler<SavedEventArgs> BeforeSaved;

    }

一个仓储基类将去实现它,当然你的仓储基类根据ORM不同,可以会有多个版本,你可以配合IOC来动态干这件事,呵呵!

如图:

这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

再看一下传统DAL层图:(比较喜欢DDD架构,对于简单业务还是可以使用这种传统架构的)

这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

好了,今天的仓储接口就讨论到这里吧,呵呵,对于一个问题的答案,在不同的场合,环境下很可能是不同的,而我们的架构也应该根据不同的业务需求,灵活去应对,这样,才会设计出更合理的架构!

本文转自博客园张占岭(仓储大叔)的博客,原文链接:这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口,如需转载请自行联系原博主。

上一篇:《Total Commander:万能文件管理器》——第8.2节.两款基本插件


下一篇:关于wordpress的一些问题