如何使用尚未存在于数据库中的实体来保存服务器生成的复杂对象树?

时间:2013-01-25 10:30:02

标签: entity-framework-ctp5 breeze savechanges

在我的水疗中心,我需要向客户端发送一个复杂的对象树,让用户填写他的数据,然后才能将实体保存在数据库中。因此,当时数据库中不存在实体。对象树在服务器的内存中构造,只需通过调用breeze.EntityQuery.from("ComplexeObjectTree")来获取。通过敲除绑定到Web表单的实体。用户首先输入所需数据,然后才能按下保存按钮。表单中的某些实体属性是可选的,并具有默认值。如果用户未更改这些属性,则beeze将不会检测到任何更改,也不会将其拥有的实体放入更改集中。它们被标记为未更改但它们的id值仍为-1(尚未保存)。但是,只有当对象树中的所有实体(包括它们的关系)都已发送到服务器(以尊重数据库约束)时,才能成功执行数据库保存。保存操作应该导致一个或多个insert语句,也适用于那些在客户端上没有更改但是对数据库不熟悉的实体(id==-1)。我该如何处理这个用例?主键id==-1的所有实体都不应该标记为已添加并且默认情况下属于保存更改集吗?

非常感谢任何帮助,

安德烈亚斯

3 个答案:

答案 0 :(得分:1)

通常,您将在客户端而不是服务器上创建实体。这样,实体就是新的,并将保存在保存方法中。

由于实体来自服务器并且它们没有在客户端上进行更改,因此服务器没有理由在它们返回时对它们执行任何操作,因为它们处于与它们离开时相同的状态。

因此,在客户端上创建新实体,然后调用保存更改。

答案 1 :(得分:1)

让我们按照您的方式行事并接受您声称必须在服务器上构建对象图的说法。如果我理解正确,您将为用户提供机会,在将它们提交到永久存储之前调整您在服务​​器上生成的一些值。听起来很精致。

“ComplexObjectTree”不必是实体图。它可以是任意数据对象。它仍然可以是CLR类型,但它不会(或包含)元数据中描述的对象,也不会为EF或Db所知。此对象图仅作为驱动客户端上实体图的构造的信息存在。它具有你不想在客户端计算的所有难以计算的值...就像生命意义的答案以及谁今年赢得超级碗一样。

您的查询返回此对象的数据但其中没有实体。 querySuccess回调CreateComplexTree(data)使用此数据在客户端上生成实体图。

由于元数据,实体图将由Breeze客户端理解的实体组成。除非你有异议,否则这些实体也可以在服务器上理解,并且可以像任何其他实体一样保存和查询(如果错误,你可以解决这个问题......但是让我们一次解决一个问题)。

所以你们都准备好了。您可以遍历数据图,随时创建实体。当您在数据中看到(-1)时,您知道要创建该类型的新实例。将数据复制到实体初始化对象中,该对象是manager.createEntity('Foo', {...})中的第二个参数。这里没有业务逻辑 - 没有计算 - 只是复制的猴子工作。

我无法判断是否要插入图表中的每个对象或仅插入其中的一些对象。可能其中一些是预先存在的实体,除非用户也更改它们,否则它们将保持不变。没什么大不了的。您可以按照相同的方法在客户端上使用类似manager.createEntity('Bar', {...}, breeze.EntityState.Unchanged)的行构建“未更改”实体。

现在您有了一个适当的Breeze实体图,可以进行绑定,导航和保存。如果用户喜欢它只是服务器创建它的方式,她按下[Save]按钮,Breeze找到实体图中的所有更改,然后关闭它们去服务器。

正如布莱恩特所说,你无法真正信任客户。您需要走图表来验证它。但无论你的方法如何,这都是正确的。

希望这有帮助。

答案 2 :(得分:0)

科比完全正确是他的回答。这个答案只是为了澄清。

我并不完全确定我理解这个问题,但只是为了清楚微风,EntityManager不支持具有相同“密钥”的相同类型的多个实体(例如在您的情况下为-1)。它将具有相同键的单个类型的所有实体视为“相同”实体。

听起来你想做的是将一堆'假'实体检索到entityManager中,然后有条件地将其中一些实体转换为'真正的'实体'并保存它们导致这些要添加到数据库的记录。这是你想要完成的事情吗?