[NewLife.XCode]实体类详解

NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。

整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中。

开源地址:https://github.com/NewLifeX/X (求star, 620+)

 

回到目录

生成实体类

上一章《数据模型》讲到模型文件Model.xml和脚本Build.tt,(nuget安装NewLife.XCode后即可拥有)。

把Build.tt和Model.xml(可改名)放在同一个目录,在Build.tt上右键“运行自定义工具”,“显示所有文件”,即可看到生成的实体类文件。

**如果运行Build.tt出错,可能是因为找不到XCode.dll文件,可以先编译一次项目,让XCode.dll生成到项目输出目录即可

我们来试试以下模型(拷贝到Model.xml里面):

640?wx_fmt=gif

<?xml version="1.0" encoding="utf-8"?>
<Tables Version="9.9.6940.24706" NameSpace="NewLife.School.Entity" ConnName="School" BaseClass="Entity" Output="">
<Table Name="Class" TableName="xxx_class" Description="班级" DbType="SqlServer">
<Columns>
<Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
<Column Name="Name" ColumnName="xxx_Nameyyy" DataType="String" Master="True" Description="名称" />
<Column Name="CreateUser" DataType="String" Description="创建者" />
<Column Name="CreateUserID" DataType="Int32" Description="创建者" />
<Column Name="CreateTime" DataType="DateTime" Description="创建时间" />
<Column Name="CreateIP" DataType="String" Description="创建地址" />
<Column Name="UpdateUser" DataType="String" Description="更新者" />
<Column Name="UpdateUserID" DataType="Int32" Description="更新者" />
<Column Name="UpdateTime" DataType="DateTime" Description="更新时间" />
<Column Name="UpdateIP" DataType="String" Description="更新地址" />
<Column Name="Remark" DataType="String" Length="200" Description="备注" />
</Columns>
</Table>
<Table Name="Student" Description="学生" DbType="SqlServer">
<Columns>
<Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
<Column Name="ClassID" DataType="Int32" Description="班级" />
<Column Name="Name" DataType="String" Master="True" Description="名称" />
<Column Name="Sex" DataType="Int32" Description="性别" Type="XCode.Membership.SexKinds" />
<Column Name="Age" DataType="Int32" Description="年龄" />
<Column Name="Mobile" DataType="String" Description="手机" />
<Column Name="Address" DataType="String" Description="地址" />
<Column Name="CreateUserID" DataType="Int32" Description="创建者" />
<Column Name="CreateTime" DataType="DateTime" Description="创建时间" />
<Column Name="CreateIP" DataType="String" Description="创建地址" />
<Column Name="UpdateUserID" DataType="Int32" Description="更新者" />
<Column Name="UpdateTime" DataType="DateTime" Description="更新时间" />
<Column Name="UpdateIP" DataType="String" Description="更新地址" />
<Column Name="Remark" DataType="String" Length="200" Description="备注" />
</Columns>
<Indexes>
<Index Columns="ClassID" />
</Indexes>
</Table>
</Tables>

640?wx_fmt=gif

运行build.tt后

640?wx_fmt=png

每个模型表,生成了四个实体类文件,选中它们并包含到项目中。

其中Biz常称之为业务类,多次build.tt生成不覆盖;

另一个称之为数据类,每次build.tt生成均覆盖;

这里采用了C#的分部类(partial)技术,一个类由两个或多个类文件组成。

数据类包含表名(类名)字段名(属性)等信息,修改模型文件后,每次生成都会覆盖文件。

业务类包含其它非表结构信息,供开发者填写代码,所以只有首次生成,而再次生成时不会覆盖。

640?wx_fmt=png

数据类包括一个接口(如IStudent),以满足精简需要的场合。

数据类内部还有两个内嵌类_和__,可用于快速访问字段信息以及属性名。

 

回到目录

实体静态构造函数

XCode是充血模型,因此实体类除了各个代表着表结构信息的属性外,还会有大量用户代码在其中,并且继承泛型实体基类(如Entity<User>)。

一个常见的实体类构造函数如下:

640?wx_fmt=gif

static User()
{
// 累加字段
var df = Meta.Factory.AdditionalFields;
df.Add(__.Logins);

// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<UserModule>();
Meta.Modules.Add
<TimeModule>();
Meta.Modules.Add
<IPModule>();

// 单对象缓存
var sc = Meta.SingleCache;
sc.FindSlaveKeyMethod
= k => Find(__.Name, k);
sc.GetSlaveKeyMethod
= e => e.Name;
}

640?wx_fmt=gif

这里首先介绍一个最重要的实体类内嵌类Meta,它位于Entity<TEntity>.Meta,记录着实体类的一切元数据,承载着实体类的一切高级功能!

 

Meta.Factory.AdditionalFields用于存放累加字段

一般更新语句 update user set Logins=123 where id=1,而把Logins字段设为累加字段后,将得到 update user set Logins=Logins+33 where id=1 ,特别适用于并发更新同一行记录的场合。

 

实体过滤器EntityModule,用于拦截实体类的添删改操作,内置最常用的3个过滤器UserModule/TimeModule/IPModule

上一章末尾推荐的8个常用字段还记得吗? CreateUser/CreateTime/CreateIP 等,所有CreateAbc将在Insert的时候拦截赋值,所有UpdateAbc将在Insert和Update的时候拦截赋值。

UserModule取当前登录用户,由ManageProvider驱动;

TimeModule取当前时间;

IPModule取当前访问IP,由ManageProvider.UserHost提供;

 

缓存配置

单对象缓存是一个字典缓存,默认以主键为key,实体对象为value。

单对象缓存支持第二个字典,如上,配置Name为第二字典的主键,实体对象为value。

 

实体基类

当然,实体类静态构造函数还可以用于其它用途,它将会在使用该实体类任意方法(包括成员方法和静态方法)之前执行。

有时候把一个系统模块放到一个独立子目录里面,独享一个“Abc.xml”模型文件,生成的实体类在目录里面,这个时候可以让它们继承一个相同的实体基类(如EntityBase)。

然后在实体基类EntityBase的静态构造函数中写入这个模块所共有的代码。

 

回到目录

初始化数据

有些数据表需要默认初始化一些数据,如类别表、配置表等,便于开发测试。

这个时候可以重载InitData方法,它会在实体类第一次访问数据库之前执行。

640?wx_fmt=png

这里遇到Meta的第二次用法Meta.Count,该属性表示当前实体类数据表的总行数。

当总行数在100万以内时,数字精确等于 select count(*) from table,大于100万时,将采用特有的快速方法。

Meta.Count带缓存,拥有极好的性能,可用于粗略(数值较小时精确)估算该表总行数。

 

这里通过Meta.Count来判断该表是否为空表,然后对空表插入一些默认数据。

 

回到目录

数据验证Valid

每个实体类在Insert/Update之前,都需要Valid验证数据 ,参数isNew以区分Insert。

640?wx_fmt=png

Valid常常可用于判断主要字段的有效性,无效时强烈推荐抛出参数类异常,魔方NewLife.Cube表单将可以捕获并定位。

除此之外,Valid用得更多的功能是在Insert/Update之前修改完善字段数据,例如上面对密码进行MD5散列,以及格式化RoleIDs。

这里出现新技术,IsDirty和Dirtys,这是XCode的脏数据,前者判断Password字段是否有脏数据(Password被赋予跟原来不想等的值),后者清空Password脏数据。

脏数据是生成Update语句的核心,不脏的字段不会出现在update set 之中,实现部分字段更新,后续有专门章节讲解。

 

回到目录

重载添删改

实体类的添删改操作都可以重载(Insert/Update/Delete/OnInsert/OnUpdate/OnDelete)

640?wx_fmt=png

640?wx_fmt=png

重载后可以做业务代码判断,也可以级联更新其它表,还可以记录添删改操作日志,甚至还可以做假删除(重载OnDelete然后实际执行OnUpdate)

分为两组重载,实际执行顺序是:Insert=>Valid=>EntityModule=>OnInsert

 

回到目录

扩展属性

XCode不支持多表关联Join,取而代之的是扩展属性!

扩展属性的意义,用到该属性时,再去查询相应数据,一般目标表带有缓存,并且扩展属性Extends也有缓存

640?wx_fmt=png

一般扩展属性复杂对象加上XmlIgnore和ScriptIgnore特性,规避Xml序列化和Json序列化。

常常还会加上 AbcName  这样的字符串型属性,头上的Map特性将在魔方NewLife.Cube展现数据时发挥极大作用。

__.ClassID表示映射到该字段,在所有显示ClassID的地方用当前属性ClassName替代;

后面的类名和字段名,表示要关联的目标表和字段,在魔方Cube表单中将直接生成下拉选择;

 

回到目录

扩展查询

实际业务中经常会用到根据某一两个字段查询的需求,例如根据主键查询。

640?wx_fmt=png

640?wx_fmt=png

一般我们把查询返回单个对象的方法命名为 FindByAbc,而把返回多个实体的方法命名为 FindAllByAbc。

上面的代码展示了3种查询方法:

通过Meta.Count判断,当总行数小于1000时,全部走Meta.Cache实体缓存表达式搜索,其原理是整表一次性载入内存,后续有专门文章介绍;

FindByID和FindByName,当总数大于1000时,走对象缓存Meta.SingleCache,按主键ID/Name为键,缓存实体对象;

不常用的FindByMail和FindAllByClassID中,用到了真正的数据库查询 Find(__.Mail, mail) 和 FindAll(_.ClassID == classid);

默认生成的代码,都带有实体缓存和对象缓存的例子,默认情况下,FindByID只需要查一次数据并载入内存,即可实现“极速查询”,后续每10秒异步更新。

显然,如果完全不需要用到缓存,直接写数据库代码就好了。

 

回到目录

高级查询

 在业务实现中经常出现超过两个甚至更多查询条件,这个时候我们推荐Search或SearchAbc

640?wx_fmt=png

XCode的查询有一套条件表达式,以WhereExpression为代表,可以动态拼接任意复杂的where查询语句。

FindAll常用两个参数,第一个条件,第二个PageParameter实现分页查询。

 

至此,简单罗列了实体类的主要构成,具体各个构成部分都将会在后面有专题文章介绍。

 

回到目录

系列教程

NewLife.XCode教程系列[2019版]

  1. 增删改查入门。快速展现用法,代码配置连接字符串

  2. 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)

  3. 实体类详解。数据类业务类,泛型基类,接口

  4. 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置

  5. 反向工程。自动建立数据库数据表

  6. 数据初始化。InitData写入初始化数据

  7. 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)

  8. 脏数据。如何产生,怎么利用

  9. 增量累加。高并发统计

  10. 事务处理。单表和多表,不同连接,多种写法

  11. 扩展属性。多表关联,Map映射

  12. 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计

  13. 数据层缓存。Sql缓存,更新机制

  14. 实体缓存。全表整理缓存,更新机制

  15. 对象缓存。字典缓存,适用用户等数据较多场景。

  16. 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存

  17. 实体工厂。元数据,通用处理程序

  18. 角色权限。Membership

  19. 导入导出。Xml,Json,二进制,网络或文件

  20. 分表分库。常见拆分逻辑

  21. 高级统计。聚合统计,分组统计

  22. 批量写入。批量插入,批量Upsert,异步保存

  23. 实体队列。写入级缓存,提升性能。

  24. 备份同步。备份数据,恢复数据,同步数据

  25. 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版

  26. 大数据分析。ETL抽取,调度计算处理,结果持久化


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF662C Binary Table(FWT_XOR卷积)

problem 洛谷链接 solution 第二次做的时候发现自己还是不会。发现自己没有写过题解&#xff0c;看来当时是没有完全搞懂的。 nnn 与 mmm 的量级相差很大&#xff0c;nnn 的范围是完全可以状压的。 不妨考虑枚举最后翻转了哪些行&#xff0c;将操作状压为一个数 XXX。 显然…

AT5662 [AGC040D] Balance Beam(二分)

前言 人类智慧&#xff0c;不可思议。 解析 考虑画出两个人的 S−TS-TS−T 折线图&#xff0c;那么答案如何表示&#xff1f; 可以理解成把 BBB 的图像不断下移&#xff0c;直到与 AAA 的图像只剩一个交点&#xff0c;此时在 xxx 轴的截矩就是答案。 设平移后 BBB 图像与 x…

Counting Triangles

Counting Triangles 题意&#xff1a; 给你一个完全图&#xff0c;每个边被赋值为0或1&#xff0c;问这个完全图中有多少个完美三角形&#xff1f; 完美三角形定义&#xff1a;三角形的三边都为0或1 题解&#xff1a; 正着求不好求&#xff0c;我们可以倒着想 不考虑完美&a…

程序员过关斩将--论商品促销代码的优雅性

点击上方蓝色字体&#xff0c;关注我们菜菜哥&#xff0c;YY说你帮她解决了几个问题&#xff0c;也帮我解决一个呗原来是D妹子&#xff0c;来坐我身边&#xff0c;说下情况我的项目是个电商项目&#xff0c;现在产品狗要给商品做活动正常呀我一个新手初来咋到顶不住压力了&…

[WC2018]州区划分(FWT_OR卷积)

problem 洛谷链接 solution 显然题目指向&#xff1a;存在欧拉回路的州划分是不合法的。 当且仅当这个州是 联通 的且 内部没有奇数度数的点 时&#xff0c;这个州不合法。 因为 nnn 非常小&#xff0c;我们可以枚举每一种州划分方案&#xff0c;判断是否合法&#xff0c;…

P5469 [NOI2019] 机器人(拉格朗日插值、区间dp)

解析 打表可得&#xff0c;有效状态大概只有 O(m)O(nlog⁡n)O(m)O(n\log n)O(m)O(nlogn) 种。 枚举最靠右的最大值位置&#xff0c;不难得到 O(mV)O(mV)O(mV) 的做法。 期望得分 505050 分。 考虑如何做 l0,r109l0,r10^9l0,r109。&#xff0c;发现前缀和后所有的 dpi,i,xxdp_…

Math(牛客多校第三场)

Math 题意&#xff1a; 问你有多少对(x,y),1<x<y<n,满足(x2 y2)%(xy1) 0 题解&#xff1a; 这种题。。。直接打表芜湖~ 通过打表发现&#xff1a;满足情况的为(i,i * i * i),但是也有不和谐的声音出现&#xff1a;当x8时&#xff0c;会出现两个&#xff0c;一个…

[NewLife.XCode]增删改查入门

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中。开源地址&#xff1a;https://github.com/…

P5472 [NOI2019] 斗主地(期望、数学)

前言 我咋连表都没打啊。 too vegetable。 解析 题目给出的洗牌形式看着并不好看&#xff0c;合理猜测可以发现&#xff0c;这其实就等价于所有可能情况等概率出现。 然后就不会了 打表可以发现&#xff1a;当 tp1 时&#xff0c;dp 数组是一个等差数列。当 tp2 时&#xff…

[HNOI2012]集合选数(思维构造 + 状压dp)

problem 题目链接 solution 从最小一个数 xxx 开始&#xff0c;将其 2x,3x2x,3x2x,3x 放入&#xff0c;再将 2(2x),3(2x),2(3x),3(3x)2(2x),3(2x),2(3x),3(3x)2(2x),3(2x),2(3x),3(3x) 放入&#xff0c;以此类推 …\dots… 将其合并为一个集合。重复又找一个最小未进入集合的…

在实际项目中使用LiteDB NoSQL数据库

LiteDB 是一个 NoSQL 数据库&#xff0c;特点是 MongoDB like 和 0 配置。100% 原汁原味的 C# 开发, Release 只有一个 DLL&#xff0c;官方有一下适用场景&#xff1a;移动App&#xff0c;桌面小应用程序&#xff0c;特有的文件格式&#xff0c;小型的 Web 应用&#xff0c;需…

2021牛客暑期多校训练营3

2021牛客暑期多校训练营3 题号题目知识点AGuess and liesBBlack and whiteCMinimum grid二分图匹配DCountEMath数论打表找规律F24dian模拟GYu Ling(Ling YueZheng) and Colorful TreeHLing Qiu, Luna and Triple BackpackIKuriyama Mirai and Exclusive OrJCounting Triangles…

P4769 [NOI2018] 冒泡排序(组合数学)

前言 这里是线性做法。 在题解里几句话说清楚的性质愣是推了一上午。 too vegetable 解析 考虑怎样的排列是不合法的。 一个排列如果不合法&#xff0c;也就是在某次交换时其中一个元素距离目标的距离没有减少反而增大了&#xff0c;那么以后这个数一定会再换回来&#xff0…

[骗分技巧——随机化Ⅰ]CodeChef-Milestones,CF364D-Ghd

文章目录CodeChef-MilestonesproblemsolutioncodeCF364D-Ghdproblemsolutioncode设随机化一次的正确率为 ppp&#xff0c;一次的复杂度为 O(f(n))O(f(n))O(f(n))。则随机的期望次数 kkk&#xff1a;k∑i1∞p(1−p)i−1i(1)(1−p)k∑i1∞p(1−p)ii∑i2∞p(1−p)i−1(i−1)(2)(1)…

初探奥尔良(Orleans)

由于工作上关系目前经常被各种并发数据问题搞得焦头烂额&#xff0c;要么要性能舍弃数据上得一致性&#xff0c;要么要一致性但是却得到了特别糟糕的响应。难道鱼和熊掌真的无法兼得吗&#xff1f;然后找到了类似奥尔良这种基于Actor模型的kuangjia首先本人因为是C#系的所以暂不…

2021杭电多校1

题号题目知识点AMod, Or and Everything思维数论BRocket landCPuzzle loopDAnother thief in a ShopEMinimum spanning tree推结论欧拉筛FXor sum01字典树GPass!HMaximal submatrix单调栈IKD-GraphJzotoKNecklace of Beads

P4775 [NOI2018] 情报中心(线段树合并)

前言 似乎也没有那么难&#xff1f; 但确实也不太好想。 解析 对于两条有交路径 (u1,v1,c1),(u2,v2,c2)(u_1,v_1,c_1),(u_2,v_2,c_2)(u1​,v1​,c1​),(u2​,v2​,c2​)&#xff0c;设 tlca(u1,u1)tlca(u_1,u_1)tlca(u1​,u1​) 为四个 lca 中最深的&#xff0c;那么代价的二…

[骗分技巧——随机化Ⅱ] [Poi2014]Couriers,CodeChef - TKCONVEX

文章目录[Poi2014]CouriersproblemsolutioncodeCodeChef - TKCONVEXproblemsolutioncode随机算法的典型套路&#xff1a;枚举太花时&#xff0c;转化为随机一个数。然后通过对正确率的分析&#xff0c;选择一个随机的次数来卡。前提是要保证每一次检验随机是否为答案的时间复杂…

[NewLife.XCode]功能设置

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中&#xff0c;代表作有百亿级大数据实时计算项…

I love max and multiply HDU - 6971(详细解答)

I love max and multiply HDU - 6971 题意&#xff1a; 数组a和b&#xff0c;现在构造一个数组c&#xff0c;使得c[k]max(a[i] * b[j]) , i&j>k 求数组c的和 题解&#xff1a; 我们可以考虑求出所有Dkmax(Ai * Bj)并满足i&jk&#xff0c;然后再从后向前取&#…