架构模式数据源模式之:表数据入口(Table Data Gateway)、行数据入口(Row Data Gateway)、活动记录(Active Record)

简介:

一:表数据入口(Table Data Gateway)

表数据入口提供了用于访问单个表或者视图(也包含了联表查询)的所有SQL,通常一个表一个类。其它代码通过它来实现对数据库的交互。基于这个特点,表数据入口和事务脚本代码以及表模块结合的很好。

在查询时候,表数据接口可以返回数据集 或者 DTO 或者 DTO列表。在 事务脚本 代码中已经阐述过了 DTO 以及 DTO 的列表这种形式。但是使用 DTO 这种形式,带来的一个问题是:到处衍生的 DTO,那么,如何减少到处衍生的 DTO 的,见这里《》。

在传统做法中,表数据入口和领域模型不一起使用,使用领域模型,一般使用数据映射器。

表数据入口的代码到处都是,如:

    public class UserDal : SqlServerDal<User> 
    { 
        public override IList<User> GetList() 
        { 
            string sql = "select * from [EL_Organization].[User] where state=1"; 
            var ds = SqlHelper.ExecuteDataset(CommandType.Text, sql);

            IList<User> oblist = new List<User>(); 
            foreach (DataRow row in ds.Tables[0].Rows) 
            { 
                oblist.Add(new User{ Id = (string)row["Id"], Name = (string)row["Name"] }); 
            }

            return oblist; 
        } 
        
        public override User FindOne(User t){ return null;} 
    
        public override void Insert(User model) {} 
        
        public override void Update(User t){}

        public override void Delete(User t){} 
    }

    public class User 
    { 
        public string Id; 
        public string Name; 
    }

 

二:行数据入口(Row Data Gateway)

行数据入口,则表中的一行记录存在一个对象。

    public class UserDal 
    { 
        public string Id; 
        public string Name; 
        
        public void Load(DataSet ds) 
        { 
            //根据 ds 得到自身,而这个 ds 有可能是从 UserFinderDal 得到的 
        } 
        
        public void Insert() 
        { 
            string sql = @"INSERT INTO [EL_Organization].[User] ('Id', 'Name') VALUES (" + this.Id + "," + this.Name + ")"; 
            var ds = SqlHelper.Execute(CommandType.Text, sql); 
        } 
        
        public void Update() 
        { 
            // update this; 
        }

        public void Delete() 
        { 
            // delete this; 
        } 
    }

    public class UserFinderDal 
    { 
        public UserDal FindOne(string id) 
        { 
            string sql = "select * from [EL_Organization].[User] where id=" + id; 
            var ds = SqlHelper.ExecuteDataset(CommandType.Text, sql);

            foreach (DataRow row in ds.Tables[0].Rows) 
            { 
                return new UserDal {Id = (string)row["Id"], Name = (string)row["Name"]}; ; 
            } 
            
            return null; 
        } 
    
        public List<UserDal> FindList(string name) 
        { 
            return null; 
        } 
    
    }

可以看到,和表数据库入口比,查询数据库中的数据,表数据库入口只要一个类就可以了,而行数据入口则需要两个类,自身也被用做数据库实体,但是负责自身的 update insert delete,而要查询自身和集合或者是操作集合,则需要另外一个类来完成。

 

二:活动记录(Active Record)

活动记录 与 行数据入口 很类似。二者的差别是 行数据入口 只有数据库访问而 活动记录 是即有数据库访问又有领域逻辑。在 行数据入口 中,我们一般使用两个类,而在活动记录中,一般则无此限制,通常情况下,一个类可能会显得更清爽。

领域模型,一般和 活动记录 或者 数据映射器 协作。

在软件开发中,初级的做法是:事务脚本;

比较高级一点的做法是:活动记录。一般,当发现事务脚本的代码已经复杂到难以维护的时候,则可以逐步创建活动记录,然后慢慢为它们添加行为,即:把表包装成为活动记录,然后添加领域逻辑。

最复杂而高级的做法是:领域模型。

从以上的描述中,我们很容易知道如何修改本文中的 表数据入口 或者 行数据入口 的代码,继而让它成为 活动记录 的。

    public class UserActiveRecord 
    { 
        public string Id; 
        public string Name; 
        
        public void Load(DataSet ds) 
        { 
            //根据 ds 得到自身,而这个 ds 有可能是从 UserFinderDal 得到的 
        } 
        
        public void Insert() 
        { 
            string sql = @"INSERT INTO [EL_Organization].[User] ('Id', 'Name') VALUES (" + this.Id + "," + this.Name + ")"; 
            var ds = SqlHelper.Execute(CommandType.Text, sql); 
        } 
        
        public void Update() 
        { 
            // update this; 
        }

        public void Delete() 
        { 
            // delete this; 
        } 
        
        public UserActiveRecord FindOne(string id) 
        { 
            string sql = "select * from [EL_Organization].[User] where id=" + id; 
            var ds = SqlHelper.ExecuteDataset(CommandType.Text, sql);

            foreach (DataRow row in ds.Tables[0].Rows) 
            { 
                return new UserActiveRecord {Id = (string)row["Id"], Name = (string)row["Name"]}; ; 
            } 
            
            return null; 
        } 
    
        public List<UserActiveRecord> FindList(string name) 
        { 
            return null; 
        } 
        
        public void SomeOtherLogic() 
        { 
        } 
    }

从上面的代码来看,活动记录这种模式不在 业务逻辑层 和 数据访问层,因为它们是一体的。而事务脚本 或者 表数据入口 和 行数据入口,多多少少可以存在两层的概念。

本文转自最课程陆敏技博客园博客,原文链接:http://www.cnblogs.com/luminji/p/3734225.html,如需转载请自行联系原作者
相关文章
|
4月前
|
小程序 Java 数据管理
Java前后端分离架构开发的智慧校园电子班牌系统源码(SaaS模式)
.智慧校园设备管理: 设备管理主要对班级中正在使用的电子智慧班牌进行管理,基本功能包含(开关机状态、班级信息、设备型号、开关机信息、电子智慧班牌截屏信息、教师编号、设备ID、在线和离线状态、电子智慧班牌更新时间等)
41 0
|
4月前
|
设计模式 Linux 程序员
Linux驱动的软件架构(一):驱动的软件设计模式理念
Linux驱动的软件架构(一):驱动的软件设计模式理念
42 0
|
4月前
|
存储 缓存 负载均衡
架构的模式
架构的模式
|
2月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
111 0
|
15天前
|
设计模式 前端开发 数据库
构建高效Android应用:使用Jetpack架构组件实现MVVM模式
【4月更文挑战第21天】 在移动开发领域,构建一个既健壮又易于维护的Android应用是每个开发者的目标。随着项目复杂度的增加,传统的MVP或MVC架构往往难以应对快速变化的市场需求和复杂的业务逻辑。本文将探讨如何利用Android Jetpack中的架构组件来实施MVVM(Model-View-ViewModel)设计模式,旨在提供一个更加模块化、可测试且易于管理的代码结构。通过具体案例分析,我们将展示如何使用LiveData, ViewModel, 和Repository来实现界面与业务逻辑的分离,以及如何利用Room数据库进行持久化存储。最终,你将获得一个响应迅速、可扩展且符合现代软件工
15 0
|
21天前
|
供应链 安全 大数据
基于B/S架构的云计算技术区域健康云HIS系统源码 SaaS多医院模式
该系统通过区域云HIS的方式,按照信息系统三级等保相关要求统一部署在总院信息中心,通过政务外网和各基层卫生院互通。基层医生打开浏览器即可访问系统。整套系统统一管理统一维护,加强系统安全防护能力,全力保障医疗卫生大数据安全。
23 5
|
25天前
|
存储 人工智能 架构师
数据库架构模式:分片
本文介绍了数据库分片的概念,以及各自的使用场景,分片可提升可扩展性、性能和高可用性。
|
28天前
|
前端开发 安全 JavaScript
计算机软件从 CS 模式到 BS 架构迁移背后的动因
计算机软件从 CS 模式到 BS 架构迁移背后的动因
30 0
|
2月前
|
存储 监控 安全
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
73 1
|
2月前
|
运维 安全 Linux
LAMP架构调优(八)——Apache Worker模式调优
LAMP架构调优(八)——Apache Worker模式调优
10 0