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; }
    }

这种方式,增删改查,都由基类处理了,而基类一般需要三个参数:

1:子类的对象,用于反射类型及属性的需要。
2:表名(可选,如果不写,则从反射中拿到类名当表名)
3:数据库链接(可选,如果不写,则会默认约定一个配置名称的数据库链接)

最终的操作方式类似:

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();

具体的方案实现可以见我以前写的这两篇文章:

C# Aop简单扫盲及ORM实体类属性拦截示例

Aop RealProxy 千年遇BUG

贫血模式的示例:

public class Users 
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public DateTime CreateTime { get; set; }
    }

这种方式,实体就类似数据载体,本身不具备增删改查功能,类似把基类独立开来操作。

最终的调用方式可能类似:

Users user= DBFast.Find<Users>(1);//查询记录。

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,1);//更新。

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万房子~~

转载于:https://www.cnblogs.com/cyq1162/p/3336662.html

ORM数据层框架的设计热点:更新指定的列的几种设计方案相关推荐

  1. 一个类GraphQL的ORM数据访问框架发布

    Zongsoft.Data 发布公告 很高兴我们的 ORM 数据访问框架(Zongsoft.Data)在历经两个 SaaS 产品的应用之后,今天正式宣布对外推广! 这是一个类 GraphQL 风格的  ...

  2. 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了

    前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...

  3. cyq.data mysql_终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了

    前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...

  4. cyq.data mysql_终于等到你:CYQ.Data V5系列 (ORM数据层,支持.NET Core)最新版本开源了...

    前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...

  5. java动态数据国际化_基于 AOP 的动态数据国际化框架的设计与实现

    定义 Aspect 的 Advice [size=1em]声明的 i18nAspect 方法有个 ProceedingJoinPoint 参数,通过它可以获得方法调用的所有信息,包括方法参数.目标对象 ...

  6. 公路—I级桥面宽度26.8m单索面预应力混凝土斜拉桥、住宅楼工程量计算及清单报价、高速公路毕业设计、六层框架综合办公楼毕业设计、住宅楼施组及施工图预算、装配式预应力混凝土连续箱梁、某框架结构住宅设计…

    [4层]4500平米框架结构大学办公楼毕业设计(含计算书,建筑.结构图,PKPM模型)--河南 [11层]10000平米框剪办公楼毕业设计(含建筑图.结构图) [2层]428平米二层框架办事处土建工程 ...

  7. java开源持久层框架集

    原文链接:http://www.open-open.com/3_18.htm Hibernate Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Ja ...

  8. 前端 重构时需要注意的事项_前端数据层落地实践

    源宝导读:天际移动平台经过重构改版,近期正式发布了1.0版本,我们在低代码开发方面做了进一步增强.本文主要围绕前端Model.前端业务逻辑(领域模型).数据层与视图层解耦(包装器模式)3个方面,给大家 ...

  9. mybatis plus关联查询_Mybatis 和 Hibernate 持久层框架之间的区别是啥?

    首先,Mybatis 和 Hibernate 都是 ORM 持久层框架,不同点在于,MyBatis 是半自动的,它需要开发人员自己手动编写 SQL 语句. 一.Mybatis MyBatis 支持通过 ...

最新文章

  1. 机器人 海难饥荒_饥荒:这个人物后期轻松单挑Boss,缺点却很小,大力士都比不过...
  2. 云炬随笔20211126(2)
  3. 13寸笔记本电脑尺寸_2020笔记本电脑推荐(华为篇)
  4. 精讲23种设计模式-基于装饰模式~设计多级缓存框架
  5. 开源合规处理方法_经济高效的开源软件许可合规模型
  6. ES6基础教程一 学习笔记
  7. R并行做大数据时间序列分析与bootstrap
  8. 虚拟服务器怎么搭建php,怎样搭建Apache+MySQL+PHP服务器
  9. Mac上几款好用磁盘分析备份管理工具
  10. 飞机遭遇时空乱流离奇穿越到30年前
  11. stream分组求和
  12. 联想Y7000安装显卡驱动
  13. wsimport生成Java客户端
  14. STM32控制0.96寸OLED(4针/4Pin)汉字以及数字,英文显示
  15. “九阳神功”是怎么炼成的?
  16. python要什么电脑配置_学Python需要什么配置的电脑?
  17. Shiro @RequiresPermissions注解是如何运转的?
  18. 卓开发中必备的那些神器APP
  19. 2023校招C++开发oppo笔试
  20. python-requests请求超时解决方案

热门文章

  1. NHibernate 学习总结 开篇
  2. sql server:删除表数据,标识列Id从1开始
  3. Linux下串口编程遇 接收数据错误问题及原因
  4. 一个方案提升Flutter内存利用率(干货)
  5. 重磅下载!业界首本强化学习应用宝典,阿里核心算法团队联袂打造
  6. html css integrity,HTML5 script 标签的 crossorigin 和integrity属性的作用
  7. react.JS并非完全开源,百度、Wordpress等带头弃之
  8. 棱镜刘大澎:云时代的手游SDK接入
  9. 用Unity盖房子(一):《勇者斗恶龙:建造者2》游戏功能的猜想
  10. 用 Unity 探究 2D 游戏的打击感