架构模式数据源模式之:表数据入口(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()
{
}
}
从上面的代码来看,活动记录这种模式不在 业务逻辑层 和 数据访问层,因为它们是一体的。而事务脚本 或者 表数据入口 和 行数据入口,多多少少可以存在两层的概念。
架构模式数据源模式之:表数据入口(Table Data Gateway)、行数据入口(Row Data Gateway)、活动记录(Active Record)的更多相关文章
- Saiku设置展示table数据不隐藏空的行数据信息(二十六)
Saiku设置展示table数据不隐藏空的行数据信息 saiku有个 非空的字段 按钮,点击这个后,会自动的把空的行数据信息给隐藏掉,这里我们来设置一下让其行数据不隐藏,为空的就为空. 主要更改两个文 ...
- 架构模式数据源模式之:数据映射器(Data Mapper)
一:数据映射器 关系型数据库用来存储数据和关系,对象则可以处理业务逻辑,所以,要把数据本身和业务逻辑糅杂到一个对象中,我们要么使用 活动记录,要么把两者分开,通过数据映射器把两者关联起来. 数据映射器 ...
- 表表达式,Substring, CharIndex, 多行数据变同一行的用法
参考: https://www.cnblogs.com/cnki/p/9561427.html https://www.cnblogs.com/johnwood/p/6386613.html 1.表1 ...
- 架构模式中的Active Record和Data Mapper
架构模式中的Active Record和Data Mapper 概念 在简单应用中,领域模型是一种和数据库结构一致的简单结构,对应每个数据库表都有一个领域类,在这种情况下,有必要让每个对象负责数据库的 ...
- QTreeView处理大量数据(使用1000万条数据,每次都只是部分刷新)
如何使QTreeView快速显示1000万条数据,并且内存占用量少呢?这个问题困扰我很久,在网上找了好多相关资料,都没有找到合理的解决方案,今天在这里把我的解决方案提供给朋友们,供大家相互学习. 我开 ...
- bootstrap-switch:记一次很坑的问题(连续相同状态的多行数据只有第一个显示按钮,其他行没有开关初始化)
先上截图,第234行都是禁用状态,但是只有第2行显示了禁用开关,后面的都没有开关初始化 检查下代码: onLoadSuccess: function(data){ {#获取行数据的状态#} conso ...
- Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle
Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq index2 3. ...
- 使用pandas导出PostgreSQL 模式下的所有表数据并保存
PostgreSQL PostgreSQL 是一个非常强大的数据库,它是一个免费的对象-关系数据库服务器(数据库管理系统).PostgreSQL支持大部分 SQL 标准, 在语句上也有很大的相似的地方 ...
- .NET应用架构设计—适当使用活动记录模式代替领域模型模式
阅读目录: 1.背景介绍 2.简单介绍领域模型模式.活动记录模式 3.活动记录模式的简单示例及要点 4.总结 1.背景介绍 对软件开发方法论有兴趣的博友应该发现最近“领域驱动设计”慢慢的被人发现被人实 ...
随机推荐
- JS跨域设置和取Cookie
在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name ...
- day10--协成\异步IO\缓存
协成(Gevent) 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.CPU只认识线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将 ...
- 【AtCoder】CADDi 2018
C - Product and GCD 题解 直接分解质因数,然后gcd每次多一个质因数均摊到每个\(N\)上的个数 代码 #include <bits/stdc++.h> #define ...
- C语言中对数组名取地址
在C/C++中,数组名相当于一个指针,指向数组的首地址.这里“相当于”不代表等于,数组名和指针还是有很多区别的,这个在<C陷阱与缺陷>里有详尽的讲述.而这里要说的是对于数组名取地址的这么一 ...
- 使用React Hooks新特性useReducer、useContext替代传统Redux高阶组件案例
当我们使用redux进行数据管理的时候,一般都是在根组件通过Provider的方式引入store,然后在每个子组件中,通过connect的方式使用高阶组件进行连接,这样造成的一个问题是,大量的高阶组件 ...
- ViewPager 无限循环
Overview 我们在使用ViewPager来制作图片轮播的时候,常常为ViewPager不能一直无限循环的问题所苦恼.对于这个问题,目前从网上找到了两个思路来解决: 将 ViewPager 的Co ...
- windows10 卸载 Docker 和 DockerNAT
删除docker程序 记事本新建脚本文件 a.ps1,内容如下: $ErrorActionPreference = "SilentlyContinue" kill -force - ...
- String和StringBuilder、StringBuffer的区别?
估计很多Java初学者在学习Java的过程中都会遇到这个问题,那就是String,StringBuilder,StringBuffer这三个类之间有什么区别?今天在这里整理一下,希望对大家有帮助哈.如 ...
- 10分钟上手python pandas
目录 Environment 开始 对象创建 查看数据 选择 直接选择 按标签选择 按位置选择 布尔索引 设置 缺失数据 操作 统计 应用(apply) 直方图化(Histogramming) 字符串 ...
- centos7 打造基于python语言Selenium2自动化开发环境
1. 准备 安装模块 # yum groupinstall "Development tools" # yum install zlib-devel bzip2-devel ope ...