DEV建议在新的XAF项目中优先采用EFCore,文章中对比了XPO与EFCore,总体来说它们各有特点,也有很多相似之处。DEV建议优先选择EFCore的原因可能与XPO一直处于维护状态有关,此外,EFCore的发展势头也越来越强劲,在XAF中使用EFCore已成为大势所趋。但是将XPO迁移到EFCore并不容易,由于XAF最初的ORM是XPO,因此某些功能是基于XPO或倾向于XPO,所以在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中的对象,这样就减少了一次提交与读取的过程。
我曾经试图去解决这个问题,为EFCore创建一个EFCoreNestedObjectSpace,EFCoreNestedObjectSpace直接采用父级的DbContext,这样可以实现在一个事务中提交,但最后发现解决一个问题,引出一堆问题,最后还是放弃了,在底层没有支持的情况下,是无法实现与XPO相似效果的。在了解了上面的内容后,我们发现,XAF中使用EFCore,与XPO相比出现的不一致行为,也不这么神秘了。但这不是全部,EFCore与XPO还是有很多不同的,如果习惯了XPO,你会发现在XPO中有许多默认行为,在EFCore中需要手动的配置,比如延迟删除、乐观并发等,这些需要注意。
关于XPO中的延迟删除(DeferredDeletionAttribute),有些小伙伴会把它当成软删除(SoftDelete),这是不正确的,它与软删除还是不一样的,虽然延迟删除不会删除记录,但它会清除记录中的外键,它的存在是为了解决XPO删除记录时,由于数据库的外键约束造成的失败,但本质还是删除,只是保留了记录,事后需要自己清理。当你试图恢复延迟删除的记录,你会发现记录与其它记录的关系没有了,这也是为什么不能用作软删除的原因。EFCore中实现软删除比较简单,使用HasQueryFilter配置实体就能实现软删除的功能,事后我会在XAF中实现一个EFCore版的软删除分享给大家。最后
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |