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

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

一:表数据入口(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()
        {
        }
    }

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

Creative Commons License本文基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
目录
相关文章
|
6月前
|
存储 NoSQL 数据库
全局id生成方式
全局id生成方式
|
3月前
|
Linux API 网络架构
【Azure 事件中心】通过 az rest --method get 如何获得Event Hub Entity 级的统计指标
【Azure 事件中心】通过 az rest --method get 如何获得Event Hub Entity 级的统计指标
|
2月前
|
数据库 Python
现在有个外键值是area_id_id,我就想他叫area_id该怎么做
现在有个外键值是area_id_id,我就想他叫area_id该怎么做
|
6月前
|
存储 缓存 算法
分布式全局id
分布式全局id
|
监控 关系型数据库 PostgreSQL
PostgreSQL 12: 新增 pg_stat_progress_create_index 视图监控索引创建进度
PostgreSQL 12 版本之前,对PostgreSQL大表创建索引时是一个比较痛苦的过程,创建索引过程中无法得知索引创建进度,PostgreSQL 12 在运维监控功能方面得到增强,新增 pg_stat_progress_create_index 视图可以监控索引的创建进度,本文简单演示。
2255 0
|
关系型数据库 数据库
【DB吐槽大会】第4期 - PG 逻辑日志只有全局开关
大家好,这是DB吐槽大会,第4期 - PG 逻辑日志只有全局开关
|
NoSQL
随笔:sending data状态包含了使用内部临时表
这是一个我的随笔记录,这些过程非常有用,也非常明显。 欢迎关注我的《深入理解MySQL主从原理 32讲 》,如下: 语句如下: mysql> desc select id,count(*) from t110 group by id; +----+-------------+-------+...
902 0
|
存储 关系型数据库 数据库
Server 层混杂信息字典表 | 全方位认识 information_schema(下)
上期《Server 层混杂信息字典表 | 全方位认识 information_schema(中)》继续为大家介绍了部分关于Server层混杂信息字典表的知识,本期“Server层混杂信息字典表(下)”将继续为大家介绍。
1140 0
|
SQL 存储 关系型数据库
Server 层混杂信息字典表 | 全方位认识 information_schema(上)
本期将为大家带来系列第四篇《Server层混杂信息字典表 | 全方位认识 information_schema》,下面请一起开始information_schema系统库的系统学习之旅吧。
1343 0
|
存储 关系型数据库 MySQL
Server 层混杂信息字典表 | 全方位认识 information_schema(中)
上期《Server 层混杂信息字典表 | 全方位认识 information_schema(上)》为大家介绍了部分关于Server层混杂信息字典表的知识,本期“Server层混杂信息字典表(中)”将继续为大家介绍。
2866 0
下一篇
无影云桌面