在BeforeSaveEntity中使用this.Context

Jul*_*ste 6 breeze

我正在寻找一种在BeforeSaveEntity方法中组织验证规则的好方法,我在文件中找到了这个注释:项目中的TodoContextProvider.cs:BreezeMvcSPATemplate:

// A second DbContext for db access during custom save validation. 
// "this.Context" is reserved for Breeze save only!
Run Code Online (Sandbox Code Playgroud)

为什么this.Context无法使用?

War*_*ard 10

好问题.答案并不明显,简单介绍并不容易.我会尝试.

EFContextProvider从客户端和取保存的数据(最终)变为这些数据转换成内部的实体EFContextProvider.Context.保存被批准后,EFContextProvider调用SaveChanges此EF上的方法Context及其所有内容将保存为单个事务.

有两个潜在的问题.

1.数据完整性和安全性

客户数据永远不可完全信任.如果您具有限制授权用户可以查看或更改的业务规则,则必须将客户端派生的实体与数据库中的相应实体进行比较.

EF Context不能包含"同一实体"的两个副本.它不能容纳具有相同密钥的两个实体.因此,您无法使用EFContextProvider.Context二者从数据库中获取干净副本并保留包含更改的副本.

你需要一秒钟Context来获得干净的副本,你必须编写逻辑来比较实体的临界值 - 保存在EFContextProvider.Context第二个中的干净实体的值Context.

2.跨实体验证

许多验证不需要将值与干净实体进行比较.

例如,开箱即用的 System.ComponentModel.DataAnnotations属性,例如Required和,MaxLength是用于确定实体是否自洽的简单数据验证.要么有价值要么没有价值.该值小于最大长度或不是.对于此类测试,您不需要比较实体.

你可以写自己的自定义System.ComponentModel.DataAnnotations是比较数据值的属性中的一个实体.您可能有一条规则,说order.InvoiceDate必须在之前或之前order.ShipDate.这也是一个自我一致性测试,你也不需要一个比较实体.

如果这些是您关心的唯一验证类型 - 并且您正在使用EF DbContext- 您可以让EF在保存处理期间为您运行它们.你不需要一秒钟Context.

跨实体验证是另一个故事.在跨实体验证中,实体"A"仅在实体"B"(可能是"C","D","E",......)的某些条件为真时才有效.例如,您可能要求订单商品具有已在数据库中的父订单.

EFContextProvider.Context您验证订单商品时,父订单很可能不在您的订单项中.

"没问题,"你说."我只会导航到父母someItem.Order."

你不能.首先,它不起作用,因为延迟加载被禁用EFContextProvider.Context.该EFContextProvider禁用延迟加载大多是序列化过程中打破循环引用又要防止性能查杀"N + 1"的错误在服务器上.

您可以通过随意加载任何实体或相关实体来解决这个问题.但是,您遇到了第二个问题:您为验证加载的实体可能与您尝试在此批次中保存的另一个实体发生冲突.

EFContextProvider不填充它Context的一次.它开始逐个验证实体,将它们添加到实体中Context.

继续我们的例子,假设我们someItem在验证期间加载了父订单.那个订单现在在EFContextProvider.Context.

保存过程继续到下一个实体并且......惊讶,惊讶......下一个实体碰巧是完全相同的父订单.在EFContextProvider尝试此副本连接到Context它已经具备了复制(我们刚刚加载的一个)......它不能.

有冲突.这两个订单中的哪一个属于EFContextProvider?我们刚刚加载的干净副本用于验证目的......或者来自客户端的修改版本要保存?

也许你认为你知道答案.也许我同意.但实际情况是,EFContextProvider抛出一个例外,因为已经有了一个带有该密钥的订单Context.

结论

如果您的所有验证都是自我一致性检查,那EFContextProvider.Context就是您所需要的.您不必创建第二个Context

但是,如果您有涉及其他实体的数据安全问题和/或业务逻辑,则需要一秒Context ......并且您需要足够的EF技能才能使用它Context.

不是Breeze或实体框架的限制.无论您选择何种技术,非平凡的业务逻辑都需要相当的服务器端复杂性.这就是野兽的本性.