XAF中XPO与EFCore的探讨

这篇具有很好参考价值的文章主要介绍了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文章来源地址https://www.toymoban.com/news/detail-451325.html

到了这里,关于XAF中XPO与EFCore的探讨的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【优选算法专栏】专题十六:BFS解决最短路问题---前言

    本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:算法从入门到精通 🚚代码仓库:小小unicorn的代码仓库

    2024年04月15日
    浏览(40)
  • linux 创建一个线程的基础开销探讨

    测试方法比较笨,每修改一次线程数,就重新编译一次,再运行。在程序运行过程中,查看到进程 pid,然后通过以下命令查看进程的运行状态信息输出到以线程数为名字的日志文件中,最后用 vimdiff 对比文件来查看内存上的差异。 每多创建一个线程,虚拟内存增长 8M 左右(

    2024年02月13日
    浏览(28)
  • 探讨PLC:一个需要一定专业性的领域?

    虽然有些人认为PLC是一个具有较高专业性的领域,但它并非完全专业化的内容。以下是一些关于PLC的观点,帮助优化表述:我这里刚好有plc、嵌入式、单片机的资料需要的可以私我或在评论区扣6 学习曲线:对于没有编程或电气知识背景的人来说,学习PLC可能会有一定的学习

    2024年02月11日
    浏览(46)
  • 深入探讨Spring Boot:实现一个完整的RESTful应用程序

    在这篇博客中,我们将深入探讨如何使用Spring Boot构建一个完整的RESTful应用程序,数据库选择MySQL。我们将通过实现一个简单的用户管理系统来演示Spring Boot的强大功能。 首先,访问Spring Initializr,选择以下依赖项: Web:用于创建Web应用程序 JPA:用于访问数据库 MySQL:用于连

    2024年02月03日
    浏览(39)
  • 探讨uniapp的页面问题

    uni-app中的页面,默认保存在工程根目录下的pages目录下。 每次新建页面,均需在pages.json中配置pages列表; 未在pages.json - pages 中注册的页面,uni-app会在编译阶段进行忽略。pages.json的完整配置参考:页面配置。 通过HBuilderX开发 uni-app 项目时,在 uni-app 项目上右键“新建页面”

    2024年02月11日
    浏览(22)
  • 探讨uniapp的数据缓存问题

    异步就是不管保没保存成功,程序都会继续往下执行。同步是等保存成功了,才会执行下面的代码。使用异步,性能会更好;而使用同步,数据会更安全。 将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。 将 data 存储在本地缓存中

    2024年02月12日
    浏览(22)
  • XAF Excel Importer

    开源项目地址:https://gitee.com/easyxaf/excel-importer 在XAF中有Excel导出,但没有Excel导入,一开始不理解,难道Excel导入很难实现吗,当我自己去实现Excel导入功能时,才发现难的不是技术,而是要有足够的灵活性,在不同的项目中或不同的业务场景中,都会有不同的需求,可能需要

    2024年02月05日
    浏览(16)
  • 深入探讨 NFT 的金融化问题

    NFT必须寻求突破, 随着NFT开始通过这些新颖的应用将更多的主流用户带入DeFi的世界,我们注意到一些主要的协议和持续的挑战。 目前,在DeFi生态系统中采用NFT的最大障碍是准确的定价和流动性。DeFi正试图解决这两个关键障碍,并取得不同程度的成功。推荐阅读本文。你别

    2024年02月02日
    浏览(27)
  • 探讨uniapp的组件使用的问题

    Flex是Flexible Box的缩写,意为“弹性布局”,用来为盒状模型提供最大的灵活性。 当设置 display: flex 后,继续给view等容器组件设置 flex-direction:row或column ,就可以在该容器内按行或列排布子组件。uni-app推荐使用flex布局, 因为flex布局有利于跨更多平台,尤其是采用原生渲染的平

    2024年02月11日
    浏览(22)
  • [230530] 托福TPO口语真题| TPO66~TPO72|XPO|Task1|20:30~21:00

    目录 真题 预测题​​​​​​​ 66. Do you agree or disagree with the following statement? Some people believe that a person needs a college education in order to have a successful career. Others believe that a college education is not necessary for success. Use details and examples to explain your opinion. 67. Some students who go to another c

    2024年02月06日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包