XAF中XPO与EFCore的探讨
首先抛出一个问题,在XAF项目中,我们现在可不可以选择EFCore?每个人可能都有自己的答案,这也没有什么标准答案。下面是我的个人看法,在刚接触XAF时,如何选择ORM,我也是犹豫了许久,最终选择了XPO,主要基于以下几点考虑
(资料图片仅供参考)
1.XPO是DEV的产品,支持力度及倾向性要比EFCore高2.XPO是XAF最开始支持的ORM,XAF中的各个模块对XPO的支持更好(有个别模块不支持EFCore)3.在XAF的社区中,关于XPO的各个方面的问题都有相应的解答,相对来说比EFCore更有优势
我想应该也有部分小伙伴可能与我的考虑是一致的,但为啥要抛出这个问题呢,是因为XAF的一篇文章(https://docs.devexpress.com/eXpressAppFramework/404186/why-we-recommend-ef-core-over-xpo)
探讨DEV建议在新的XAF项目中优先采用EFCore,文章中对比了XPO与EFCore,总体来说它们各有特点,也有很多相似之处。DEV建议优先选择EFCore的原因可能与XPO一直处于维护状态有关,此外,EFCore的发展势头也越来越强劲,在XAF中使用EFCore已成为大势所趋。但是将XPO迁移到EFCore并不容易,由于XAF最初的ORM是XPO,因此某些功能是基于XPO或倾向于XPO,所以在EFCore上的效果可能会有所不同。
虽然XPO和EFCore在语法上有许多不同,但在思想上基本一致。大部分XPO中的特性都被EFCore支持,但是有一个EFCore没有的特性,即NestedUnitOfWork,在EFCore中对应NestedDbContext,但EFCore没有。XAF利用XPO的这个特性构建了XPNestedObjectSpace,使父子表(或主从表)之间的操作更加自然和灵活。
由于EFCore没有这个特性,因此使用起来与XPO的操作不一致,甚至会给人一种不可接受的感觉。下面通过刨析它们内部的原理,来讲解它们行为不一致的原因,同时不可接受的地方,通过了解后是否可以接受它。
首先讲一下,在XPO中习以为常的功能,在EFCore中却会出现不一样的行为。这主要出现在父子表中,或者说聚合实体中,这里假设一个场景,用户表(User)中包含一个用户标记(UserTag)列表(Tags),它是聚合的(Aggregated),这是一个一对多的关系。当我们新建User后,再向Tags列表中添加UserTag时,在EFCore下,会自动保存User,而在XPO中不会有这样的操作,这样会造成一个问题,如果此时,我想放弃当前新建的User,我把User关闭后,列表中会多一条刚才放弃的User,这种现象在XPO中是没有的,为什么会有这样不一致的行为呢。这就是前面提到的XPNestedObjectSpace,而EFCore没有这样的一个实现。
这里要引出XPO中的Session,它与EFCore的DbContext是对应的(确切的说与UnitOfWork更像),Session有多个子类如UnitOfWork,NestedUnitOfWork,ExplicitUnitOfWork,通过名称我们也可以了解它们的用途,我们平时在创建BO类时,都要有一个包含Session参数的构造函数,这里的Session一般都是它的子类UnitOfWork,Session中的事务比较简单,我们在调用BO对象中的Save方法时,就会直接提交到数据库。UnitOfWork又多了一层,调用BO对象中的Save方法时,并不会立即提交到数据库,我们需要调用UnitOfWork中的CommitChanges方法,它会将工作单元中的BO对象一并提交到数据库,而ExplicitUnitOfWork会启用一个显式事务(也称作数据库级事务),我们通过BeginTransaction方法开启事务,通过CommitTransaction方法提交事务,在没有提交之前,你可以多次调用CommitChanges方法,如果其中一个提交出现异常或其它原因放弃提交,你可以通过RollbackTransaction方法回滚事务,这样就可以将之前的所有提交都进行回滚。
NestedUnitOfWork是我们需要重点关注的,它就是嵌套工作单元,你也可以把它看作是UnitOfWork的子工作单元,它有一个好处就是,它可以直接访问到父级中的对象也就UnitOfWork中的对象,同时它提交时,并不会直接提交到数据库,而是等待父级的UnitOfWork一起提交,它们的提交是放在同一事务中的,如果NestedUnitOfWork不提交,而父级UnitOfWork进行了提交,此时提交的内容不会包含NestedUnitOfWork中的对象。
以上NestedUnitOfWork的特点带来许多好处,如可以使父子表间的编辑变的简单,父表提交时,可以一起提交子表,父表放弃后,子表也会放弃,子表也可以随时单独放弃等等,当与XAF的主从视图结合时,就会有很不错的操作体验。
如果没有NestedUnitOfWork,将会发生什么呢,首先两个UnitOfWork是不能直接通信的,其中一个UnitOfWork创建的对象,如果另一个UnitOfWork想访问,第一个UnitOfWork需要先提交到数据库,第二个UnitOfWork再从数据库中读取,而NestedUnitOfWork可以直接通过GetObject方法访问到父级UnitOfWork中的对象,这样就减少了一次提交与读取的过程。
再回到前面创建User的示例,由于UserTag与User是聚合关系,也就是UserTag只属于一个User,同时UserTag中的User外键还不能为空,也就是说UserTag脱离User,它本身就没有意义,相当于订单与订单明细的关系。在这种情况下,我们在User中新增UserTag时,UserTag首先需要一个User,而如果此时User也是新建的,并且它们分别在不同的UnitOfWork中时(在XAF的主从视图中,如果新建从表数据,XAF会单独创建一个ObjectSpace,也就是当前User与UserTag会在不同的ObjectSpace中),我们能想到的就是保存User,在UserTag所在的UnitOfWork中从数据库中读取User。
看到这里的小伙伴应该明白了,XAF为什么会在新增UserTag时需要保存User了吧。我们刚才谈到的是聚合关系,如果不是聚合的一对多关系是否会自动保存父级呢,不会的,因为不是聚合,那它的外键可以为空,也就是UserTag的User外键可以为空,这样在新建时,可以不必事先获取父级,那也就没必要保存父级了。
前面讲的都是新建的User,如果是已存在的User,也就是从列表中打开的User,如果在User中新增UserTag会不会自动保存呢,也不会,因为User已存在于数据库中,在UserTag的UnitOfWork中就可以从数据库中获取到User,这样也没有必要保存User。如果仔细观察,在没有修改User的情况下,新增UserTag,保存按钮还是处于禁用状态,这是由于它们处在不同的UnitOfWork中互不干扰。
在EFCore中,将上面的UnitOfWork替换为DbContext,也就知道了为什么EFCore会出现与XPO不一致的行为了,这里的关键点就是NestedUnitOfWork,而EFCore没有对应的实现,那是不是EFCore就不是一个好的选择呢,我倒觉得不是,通过上面的示例,我们可以看到,除了在新建具有聚合关系的对象时,会出现与XPO不一致的行为,其它的地方与XPO基本保持一致。
随手创建,随手放弃,可能是我们日常测试时经常操作的,但是在上线运行时,日常操作会有相关的约束,不会频繁出现这样的行为,再加上XAF自动保存时也会进行数据校验,校验不通过也是无法进行自动保存的,同时由于Blazor自身的特点,对于一些需要长时间录入的页面,我们还需要自己加入自动保存的功能,已防止录入数据的丢失。
我曾经试图去解决这个问题,为EFCore创建一个EFCoreNestedObjectSpace,EFCoreNestedObjectSpace直接采用父级的DbContext,这样可以实现在一个事务中提交,但最后发现解决一个问题,引出一堆问题,最后还是放弃了,在底层没有支持的情况下,是无法实现与XPO相似效果的。
在了解了上面的内容后,我们发现,XAF中使用EFCore,与XPO相比出现的不一致行为,也不这么神秘了。但这不是全部,EFCore与XPO还是有很多不同的,如果习惯了XPO,你会发现在XPO中有许多默认行为,在EFCore中需要手动的配置,比如延迟删除、乐观并发等,这些需要注意。
最后关于XPO中的延迟删除(DeferredDeletionAttribute),有些小伙伴会把它当成软删除(SoftDelete),这是不正确的,它与软删除还是不一样的,虽然延迟删除不会删除记录,但它会清除记录中的外键,它的存在是为了解决XPO删除记录时,由于数据库的外键约束造成的失败,但本质还是删除,只是保留了记录,事后需要自己清理。当你试图恢复延迟删除的记录,你会发现记录与其它记录的关系没有了,这也是为什么不能用作软删除的原因。EFCore中实现软删除比较简单,使用HasQueryFilter配置实体就能实现软删除的功能,事后我会在XAF中实现一个EFCore版的软删除分享给大家。
随着XAF中使用EFCore的深入,可能还会发现与XPO的不同,或出现一些无法解决的问题,我都会更新到文章中。当我完全切换到EFCore时,可能今后就要远离XPO了,有些不舍,但总要去面对,新技术总会取代旧的技术。
https://www.cnblogs.com/haoxj/p/17416380.html
标签:
为您推荐
广告
- XAF中XPO与EFCore的探讨
- 简讯:“大国重器” 驶向全球 跟随记者探访江苏先进造船工厂
- 罗红霉素胶囊治感冒吗嗓子疼_罗红霉素胶囊可以治感冒吗 天天最资讯
- 江西九江:金穗飘香 颗粒归仓
- 可爱多是谁的粉丝名_可爱多 曾轶可粉丝名称
- 《赛博朋克2077》“往日之影DLC”将于6月8日发售
- 当前关注:结膜炎和角膜炎的图片_结膜炎图片
- 股票行情快报:瑞鹄模具(002997)5月19日主力资金净卖出286.74万元
- 当前简讯:如何用word自动生成目录_word如何自动生成目录
- 内双怎么画眼线_内双画眼线的方法简述
- 特斯拉新车或售17万,会引发怎样的车市地震?哪些车企会坐不住?
- 研究发现与抑郁症有关的肠道微生物组被破坏_今日讯
- 岢岚县气象局发布沙尘蓝色预警【Ⅳ级/一般】【2023-05-19】
- 凯特·布兰切特亮相戛纳photocall 新片《新男孩》入围一种关注单元 当前速递
- 抖音月付资质不够怎么办?这5个小技巧或许能帮到你 全球焦点
- 如何从深圳湾去香港机场(深圳大巴车费用是多少)
- Ideanomics报告第四季度和2022年全年财务业绩-世界要闻
- N飞测-U(688361):聚焦半导体检测量测设备 国产替代正当时-全球观焦点
- 收缩还是放权?合资车企站在十字路口
- 香港中文大学专家参访团赴福建宁德考察
- 1天天关注:MAKE UP FOR EVER体验站携仿真肌家族登录长沙王府井 带你玩转潮妆
- 2ps名片设计制作教程 ps名片制作步骤
- 3笃行是什么意思(笃定是什么意思)
- 4天天观察:中原:展望第2季CRI回报率止跌回升
- 5ina轴承是哪国的_fag轴承是哪个国家的_头条焦点
- 6西双版纳州部署专项整治工作 “剑指”道路运输行业突出问题|今日精选
- 7差异化布局“冷门赛道” 基金掘金大众消费股 环球看点
- 8Gumayusi:弥补不足还是能夺冠,感觉GEN状态更好将击败BLG
- 9大额存单卖爆了:5000万额度,上架仅3分钟被抢光
- 10最新快讯!2023年上海市全民数字素养与技能提升月闵行区活动拉开帷幕
广告
- 天天观热点:怎样卸下纱窗_窗纱怎么卸下来简介介绍
- 国家医保为患者减负超5000亿元 国家集采药品平均降价超50%|世界观点
- 两盏路灯照亮回家的路 泉口街为群众办实事-环球新资讯
- 全球头条:利扬芯片:拟不超3.5亿元投设两家全资子公司
- 大宗交易:财信发展成交4466万元,折价2.87%(05-18)
- 管城经济技术开发区倾力打造“五心”营商环境品牌,做好企业项目的“大后方”和“总后勤”|世界速看料
- 每日热门:Instagram 终于可以让你留下 GIF 评论了
- 环球动态:单排脚手架连墙件设置要求
- 资讯推荐:自身原因无法休年假 职工能否获补偿?
- 信用卡逾期了公安备案怎么办?信用卡逾期跟公安局有关系吗?|最新资讯
- 环球热门:长沙商贸旅游职院举办红色导游词讲解比赛
- 智谱AI 张帆:只有做到千亿模型 才是人工智能生成内容的船票 每日时讯
- 安帅糟糕?瓜帅为安帅辩护:你错了!皇马首场本有机会 这就是足球 消息
- 天天看点:春夏之交,太原动物园“生”机勃勃
- 进球网:尽管安帅表态将留队,但他前往巴西的大门并未锁上-全球热点
- 湖南今明两天晴天唱主角 明晨湘西有雾扰注意防范 全球消息
- 甘肃省宁县市场监管局开展化妆品经营环节专项检查-环球报道
- 赋能千行百业 中国北斗系统进入规模应用发展快车道-今日关注
- 全球热文:六盘水站始发!贵州首趟直达塔河旅游专列开行
- 当前消息!松霖科技(603992):5月18日技术指标出现看涨信号-“红三兵”
