ORM数据层框架的设计热点:更新指定的列的几种设计方案
ORM框架的定义:对象-关系映射(Object/Relation Mapping,简称ORM)
常见的是:数据库结构=》映射Object(实体属性)=》基于实体类的操作。
还有一种:数据库结构=》映射Object(内存表结构)=》基于内存表的操作。
当然,如果你有创意,你还能创造出更多的映射载体来实现ORM。
避免思维定式:
由于思维定式,很多开发者,只有见到基于实体类映射,才会认为是一种ORM框架,于是很少人去思考其它映射载体来实现ORM。
这个思维定式,和早期在ASP.NET MVC没出来之前,把WebForm框架当成ASP.NET一样,于是很少人会去创造另一种开发框架。
不过要避免思维定式,有时候的确不是件容易的事~~~这需要太多知识的沉淀和积累,这个就先不扯了,下面来正题。
ORM生成SQL:
一般的数据库下,都是基于SQL语句解析执行的,所以ORM最终都避不开生成SQL再交还ADO.NET去执行,从而返回结果。
由于ORM存在映射关系,最简单的是(字段名称+数据类型)的实体映射,因此,通常只要遍历实体的属性就可以拿到所有字段名称,从而组合SQL去执行了。
而反射的应用,对于实体型映射的ORM无疑是佳方案,节省大量代码;通过反射,在处理时动态获得指定对象的类型、字段名称、字段类型、或者特性描述等信息,从而构造出SQL语句。
如果是基于内存表(MDataTable)映射的,则无需反射,因为映射的时候,相关结构已提前预约好了,直接遍历获取即可。
ORM的两种实体型实现方式:充血和贫血
这里先不说基于内存表的映射,说说基于实体映射的设计方案:
充血模式的示例:
public class Users : CYQ.Data.Orm.OrmBase
{
public Users()
{
base.SetInit(this);
}
public int ID { get; set; }
public string UserName { get; set; }
public DateTime CreateTime { get; set; }
}
这种方式,增删改查,都由基类处理了,而基类一般需要三个参数:
:子类的对象,用于反射类型及属性的需要。
:表名(可选,如果不写,则从反射中拿到类名当表名)
:数据库链接(可选,如果不写,则会默认约定一个配置名称的数据库链接)
最终的操作方式类似:
using (Users u = new Users())
{
u.UserName = "u1";
u.Update(1);
}
如果按常规,我们可能会循环所有字段,全部更新;很明显在这里我们只需要更新UserName。
于是,在设计上,我们需要额外多出一个集合,来存储字段对应的状态,这个集合怎么设计,这个大伙自行发挥了。
这里的难点,在于,如何设计获取状态改变上。
充血模式的两种更新指定列的设计方案:
1: 把动作交给实体,这种方案比较常规,动动脑就想的出来:
直接切入实体的Set属性,如:
public string UserName
{
get;
set
{
base.SetState(value);
}
}
然后事情就交给基类的SetState方法去修正对应实体的状态,遍历属性的时候,再比较状态,取得只需要更新的字段去组合即可。
2:把动作交给基类:利用AOP动态拦截属性,这种方案实现相对复杂
这种方案,优点是:可以保持实体类的相对简洁,通过在基类利用AOP拦截子类的Set方法,从而动态的调用SetState方法。
缺点是:实现有点难度,另外是由于AOP基类ContextBoundObject的限制, 内部无法使用泛型。
即你不能实现:Select<T>()类似的方法,所以最终的表达式可能需要借第三个类的ToList()方法来返回,代码类似:
using(Users u = new Users())
{
List<Users> list= u.Select().ToList();
}
具体的方案实现可以见我以前写的这两篇文章:
贫血模式的示例:
public class Users
{
public int ID { get; set; }
public string UserName { get; set; }
public DateTime CreateTime { get; set; }
}
这种方式,实体就类似数据载体,本身不具备增删改查功能,类似把基类独立开来操作。
最终的调用方式可能类似:
Users user= DBFast.Find<Users>();//查询记录。 Users u=new Users();
u.UserName="u1";
DBFast.Update<Users>(u,1);//更新。
贫血模式的两种更新指定列的设计方案:
对于贫血模式,也有两种对应的设计方案:
1:实体还是原生态的:
public class Users
{
public int ID { get; set; }
public string UserName { get; set; }
public DateTime CreateTime { get; set; }
}
由于没有基类,所以状态的变化,无法很好的集成的,因此,这种情况的设计,通常需要多一行额外的代码来传递信息。
例如:
Users u=new Users();
u.UserName="u1";
DBFast.SetState<Users>("UserName",State.ForUpdate);//类似的多了一行来指定需要更新的一个或多个列的状态。
DBFast.Update<Users>(u,);//更新。
2:可以Nullable的实体:
public class Users
{
public int? ID { get; set; }
public string UserName { get; set; }
public DateTime? CreateTime { get; set; }
}
对于这种模式,可以让值类型的默认值也为Null,因此可以通过减免值为Null的列,来实现更新值不为Null的值。
不过对于这种方式,由于DBNull.Value只能给引用类型赋值,因此值类型的字段无法重置为Null。
所以,如果要实现对值类型赋Null值,可能需要增加一行代码来对指定的行指定状态,配合着使用;或者直接操作SQL语句。
总结回忆:
记得前些日子和腾讯的架构师面试的时候,好像也交流到了这个指定列的更新的话题上,不过那时候的话题,上升到分布式话题了:
问题:大体是有一份数据载体情况下,用户更新了某些字段,如何只更新某些字段的话题:
1:先是说前端的过滤与传递只需要更新的数据(对方:这个先假设没有做)。
2:服务端可以做缓存,然后比较(对方:假设服务器有很多,做了负载,如何保证)。
3:全局共享缓存或用分布式缓存(对方:假设没有分布式缓存,只有Web服务器缓存,只有一份副本)
4:通过某种算法,让用户的请求的数据对应到相对的副本的服务器。(对方:算法怎么实现)
5:。。。此处省略600字了。。。
不知不觉又写了好几个小时了,今天就介绍到这里了~~~谢谢大伙~~~~
最后给贴一下今天各大群热传的励志文:月领1万2小IT职员五年在北京买500万房子~~

ORM数据层框架的设计热点:更新指定的列的几种设计方案的更多相关文章
- 一个类GraphQL的ORM数据访问框架发布
Zongsoft.Data 发布公告 很高兴我们的 ORM 数据访问框架(Zongsoft.Data)在历经两个 SaaS 产品的应用之后,今天正式宣布对外推广! 这是一个类 GraphQL 风格的 ...
- JAVA 利用反射自定义数据层框架
之前的随笔一直都在介绍c#,主要公司最近的业务都是做桌面程序,那么目前c#中的WPF肯定是我做桌面程序的不二之选,做了半年的WPF,也基本摸清了c#写代码的套路和规则(本人之前是两年多的JAVA开发者 ...
- 【mybatis xml】数据层框架应用--Mybatis(三)关系映射之一对一关系映射
实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系. 针对多表之间的操作,MyBatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关 ...
- 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了
前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...
- 分享自己的超轻量级高性能ORM数据访问框架Deft
Deft 简介 Deft是一个超轻量级高性能O/R mapping数据访问框架,简单易用,几分钟即可上手. Deft包含如下但不限于此的特点: 1.按照Transact-SQL的语法语义风格来设计,只 ...
- 终于等到你:CYQ.Data V5系列 (ORM数据层,支持.NET Core)最新版本开源了
前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...
- CYQ.Data 开源数据层框架 官方下载
CYQData 数据框架 介绍: CYQ.Data 是一款操作数据库用的数据框架:安全稳定.简洁易用.功能强大.性能优越.内置支持多数据库.多语言.RSS.AOP.事务等功能. 使用本框架进行开发,入 ...
- 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD
使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...
- 【mybatis annotation】数据层框架应用--Mybatis(二) 基于注解实现数据的CRUD
使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...
随机推荐
- 第六课 touch事件
1.移动端页面在PC上浏览时,限制宽度的方法: 2.移动端页面切换设备时自动刷新页面的方法: 3.touch事件 touchstart:当手指触摸屏幕时触发.通过addEventListener添加移 ...
- ExtJS基础知识总结:自定义日历和ComboBox控件(二)
概述 1.ExtJS 5不支持日期选择框中只选择年月,为了满足ExtJs5可以实现选择年月的功能,查询网上资料,整理出来了相应的处理方式,最终实现的效果如下图: 2.ExtJS 控件丰富,如果需要实现 ...
- C 标准库系列之概述
基本上很多编程语言都会提供针对语言本身的一系列的标准库或者包,当然C语言同样也有提供标准库,C语言的标准库是一系列的头文件的集合:如assert.h.ctype.h.errno.h.float.h.l ...
- 【python坑记录】
python的sort函数使用的时候有一个参数cmp.一定注意这里返回值要用1和-1.不能True和False!!!
- GDB的常用命令
定断点b line.会返回一个断点号(breakpoint-no). 输出p val.可以夹杂类型装换.解引用. 遇到断点自动执行命令commands breakpoint-no. 停止执行s. 退出 ...
- 谈谈iOS中的屏幕方向
众所周知,iOS中提供了[UIDevice currentDevice].orientation与[UIApplication sharedApplication].statusBarOrientat ...
- linux线程
线程:轻量级进程,在资源.数据方面不需要进行复制 不间断地跟踪指令执行的路径被称为执行路线 进程的结构:task_struck:地址空间 线程:轻量级的进程 在同一个进程中创建的线程,在共享进程的地址 ...
- Linux 操作mysql数据库 创建库 导入、删除表
确保线上的运行数据库是不可避免的本人小白,因公司上线没有办法自己去整服务器,深刻体会到服务器大神的霸气,所以为了增加记忆,服务广大员友记录一下 linux mysql 忘记root的密码无法登陆进my ...
- iOS Swift 3 open
参考资料:http://stackoverflow.com/questions/38947101/what-is-the-open-keyword-in-swift
- 关闭rdlc报表打印预览后,关闭客户端,抛出异常“发生了应用程序级的异常 将退出”
问题:关闭rdlc报表打印预览后,关闭客户端,抛出异常“发生了应用程序级的异常 将退出” 办法:在容纳ReportViewer的窗体后台代码中,添加如下代码即可 protected override ...