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

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

架构模式数据源模式之:表数据入口(Table Data Gateway)、行数据入口(Row Data Gateway)、活动记录(Active Record)的更多相关文章

  1. Saiku设置展示table数据不隐藏空的行数据信息(二十六)

    Saiku设置展示table数据不隐藏空的行数据信息 saiku有个 非空的字段 按钮,点击这个后,会自动的把空的行数据信息给隐藏掉,这里我们来设置一下让其行数据不隐藏,为空的就为空. 主要更改两个文 ...

  2. 架构模式数据源模式之:数据映射器(Data Mapper)

    一:数据映射器 关系型数据库用来存储数据和关系,对象则可以处理业务逻辑,所以,要把数据本身和业务逻辑糅杂到一个对象中,我们要么使用 活动记录,要么把两者分开,通过数据映射器把两者关联起来. 数据映射器 ...

  3. 表表达式,Substring, CharIndex, 多行数据变同一行的用法

    参考: https://www.cnblogs.com/cnki/p/9561427.html https://www.cnblogs.com/johnwood/p/6386613.html 1.表1 ...

  4. 架构模式中的Active Record和Data Mapper

    架构模式中的Active Record和Data Mapper 概念 在简单应用中,领域模型是一种和数据库结构一致的简单结构,对应每个数据库表都有一个领域类,在这种情况下,有必要让每个对象负责数据库的 ...

  5. QTreeView处理大量数据(使用1000万条数据,每次都只是部分刷新)

    如何使QTreeView快速显示1000万条数据,并且内存占用量少呢?这个问题困扰我很久,在网上找了好多相关资料,都没有找到合理的解决方案,今天在这里把我的解决方案提供给朋友们,供大家相互学习. 我开 ...

  6. bootstrap-switch:记一次很坑的问题(连续相同状态的多行数据只有第一个显示按钮,其他行没有开关初始化)

    先上截图,第234行都是禁用状态,但是只有第2行显示了禁用开关,后面的都没有开关初始化 检查下代码: onLoadSuccess: function(data){ {#获取行数据的状态#} conso ...

  7. Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle

    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq  index2 3.  ...

  8. 使用pandas导出PostgreSQL 模式下的所有表数据并保存

    PostgreSQL PostgreSQL 是一个非常强大的数据库,它是一个免费的对象-关系数据库服务器(数据库管理系统).PostgreSQL支持大部分 SQL 标准, 在语句上也有很大的相似的地方 ...

  9. .NET应用架构设计—适当使用活动记录模式代替领域模型模式

    阅读目录: 1.背景介绍 2.简单介绍领域模型模式.活动记录模式 3.活动记录模式的简单示例及要点 4.总结 1.背景介绍 对软件开发方法论有兴趣的博友应该发现最近“领域驱动设计”慢慢的被人发现被人实 ...

随机推荐

  1. 【PAT】1060 Are They Equal (25)(25 分)

    1060 Are They Equal (25)(25 分) If a machine can save only 3 significant digits, the float numbers 12 ...

  2. Angular快速学习笔记(4) -- Observable与RxJS

    介绍RxJS前,先介绍Observable 可观察对象(Observable) 可观察对象支持在应用中的发布者和订阅者之间传递消息. 可观察对象可以发送多个任意类型的值 -- 字面量.消息.事件. 基 ...

  3. Windows网络命令

    如何查看系统端口 Windows中要查看系统端口,可以使用netstat命令,点击开始---运行---键入cmd,打开命令提示符窗口,在命令提示符状态下键入“netstat -an”,按下回车键后就可 ...

  4. [C] 错误笔记:函数调用——值传递

    前提: 写一个函数,功能为在堆内开辟一块空间,并将首地址以函数参数的形式返回主调函数 错误demo void test(char *a) { ] = "hello"; printf ...

  5. ref:linux用户和组管理,/etc/passwd,/etc/shadow和/etc/group 文件内容解释

    ref:https://www.cnblogs.com/xuha0/p/5519232.html 与用户相关的系统配置文件主要有/etc/passwd 和/etc/shadow,其中/etc/shad ...

  6. ADNI数据集相关概念整理

    数据类型 临床 遗传 MRI图像 PET图像 生物样本 临床 ADNI临床数据集包括关于每个受试者的临床信息,包括招募,人口统计学,身体检查和认知评估数据.可以将整套临床数据作为逗号分隔值(CSV)文 ...

  7. js加入购物车抛物线动画

    天猫将商品加入购物车会有一个抛物线动画,告诉用户操作成功以及购物车的位置,业务中需要用到类似的效果,记录一下实现过程备忘,先上demo 一开始没有想到用抛物线函数去做,也已经忘记还有这么个函数了,想着 ...

  8. 每日踩坑 2018-12-25 【Unable to convert MySQL date/time value to System.DateTime】异常

    之前的公司一直是用 ORM ,所以底层的事情完全不用在意, 到了这家全是似乎全是 SQL 硬编码 所以也有机会重新去补补以前也没怎么写过的基本 ADO. 不过这两天总有自己写个简易ORM的想法在蠢蠢欲 ...

  9. [TJOI2015]线性代数

    OJ题号:BZOJ3996 题目大意: 给定一个矩阵$B_{nn}$,矩阵$C_{1n}$,存在一个01矩阵$A_{1,n}$使得$d=(A\times B-c)\times A^\mathsf{T} ...

  10. KVM源代码解读:linux-3.17.4\arch\x86\include\asm\kvm_host.h

    /* * Kernel-based Virtual Machine driver for Linux * * This header defines architecture specific int ...