如何使用breezejs从服务器获取新的(EntityState.New)实体 [英] How to fetch new (EntityState.New) entities from server with breezejs
问题描述
我有一个Web服务,该服务返回一些数据,然后将这些数据转换为服务器上的新实体,然后传递给客户端,用户可以在其中编辑它们。如果他选择 SaveChanges
,则应将实体提交到服务器并插入数据库。我有两个问题:
I have a web services that returns some data, which is then transformed into new entities on the server and then passed to the client, where user can edit them. If he chooses to SaveChanges
, the entities should be submitted to the server and inserted into database. I have two problems:
- 当实体退还给客户时,Breeze将其标记为
EntityState.New
- Breeze期望未更改的实体具有主键集。因为没有返回的新实体都具有键集(类型Int32的键值等于0),所以Breeze认为服务器返回了同一实体的多个实例
为演示该问题,请更改AngularJS示例中的 ToDosController.ToDos
方法以匹配以下内容:
To demonstrate the problem, change the ToDosController.ToDos
method in AngularJS sample to match the following:
[HttpGet]
public IEnumerable<TodoItem> Todos()
{
return new TodoItem[]
{
// Keys are not set because (equals to 0) these are new entities
new TodoItem() { Description="First item"},
new TodoItem() { Description="Second item"},
};
}
运行示例时,HTML页面将显示两行,两行有描述第二项。如果我在服务器上明确设置了这些项的ID(我不想这样做,因为密钥是由数据库生成的),则问题就不会显现出来。
When you run the sample, the HTML page will shows two lines, both will have description "Second item". If I explicitly set the Ids of those items on the server (which I do not want to do, because the keys are generated by database), the problem is not manifested.
问题:如何从服务器正确返回实体,以便将它们标记为 EntityState.New
,并在<时将其保存到数据库中(带有生成的键) code> SaveChanges 被调用。
The question: how to correctly return entities from the server, so that they will be marked as EntityState.New
and they will be saved into database (with generated keys) when SaveChanges
is called.
我希望某些 MergeStrategy
客户端或服务器上的一些其他数据/属性来实现此目的,但找不到一个。
I would expect some MergeStrategy
on the client or some extra data/attribute on the server to achieve this, but was unable to find one.
更新:
要澄清一下:
我尝试支持一种方案,当用户选择并编辑一个源自其他实体的实体时
I am try to support a scenario when users selects and edits one of the entities which originate from some other source, that should be later added to my database.
详细信息:
-
客户端使用搜索条件作为方法参数调用服务器。服务器方法返回
IEnumerable< Customer>
-它不会不返回IQueriable< Customer>
服务器查询后端Web服务(CRM系统)并将后端Web服务的结果转换为 Customer
实体。结果返回给客户端。客户端无法使用后端Web服务。
Server queries a backend web service (CRM system) and transforms the result of backend web service into Customer
entities. The result is returned to the client. The backend web service is not available to the client.
客户端将结果显示给用户
Client displays the result to the user
用户选择一个实体并编辑其属性(例如更改客户名称或地址)
User selects one of the entities and edit its properties (such as change customer name or address)
所选客户将添加到实体管理器上客户端。它应该位于 EntityState.Added
The selected customer is added to entity manager on the client. It should be in the EntityState.Added
em.SaveChanges
被调用,它向服务器提交 Add
ed实体
em.SaveChanges
is called, which submits the Add
ed entity to the server
服务器插入新客户进入数据库,数据库生成新的主键,该主键返回给客户端,EM在此更新实体键并将实体状态设置为 EntityState.Unchanged
Server inserts the new customer into database, database generates new primary key, which is returned to the client, where EM updates the entity key and set entity state to EntityState.Unchanged
也许我需要分离的实体,正确的问题是:如何在不将实体添加到客户端的情况下将其返还给客户经理?((它们将在上面的第5步中添加)。
Maybe I need detached entities and the right question is: "How to return entities to the client without adding them to entity manager?" (they will be added in step 5 above).
PS:
一种解决方案是使用自定义的非我的服务器方法产生的实体数据类型(例如CustomerFromCRM)。然后,我将它们转换为客户端上的实体Customer。但是我想避免创建其他类。
P.S: One solution would be to use a custom, non-entity datatype (such as CustomerFromCRM) as result of my server method. I would then transform them to entity Customer on the client side. But I would like to avoid creating additional classes.
UPDATE2:我在这里找到了类似的问题(没有被接受的回答):是否有一种简单的方法将缓存中的实体标记为添加?
UPDATE2: I have found a similar question (with no accepted answere) here: is there an easy way to mark an entity in the cache as "added"?
推荐答案
回答我自己的问题:
我能够通过修改微风源代码(不附加任何内容)来使其工作实体设置为 EntityManager
(如果设置了指定的标志)。我可以定义自定义 MergeStreategy
,但是由于我不想弄乱微风代码中的枚举,因此我定义了自定义文件 FetchAsDetached $我自定义实现
JsonResultAdapter.visitNode
方法返回的对象上的c $ c>。
I was able to get this working by modifying breeze source code in a way, that it does NOT attach entities to EntityManager
if specified flag is set. I could define custom MergeStreategy
, but since I didn't want to mess with enums in breeze code, I've defined custom filed FetchAsDetached
on an object returned from my custom implementation of JsonResultAdapter.visitNode
method.
我必须更改 mergeEntity
函数的方式如下:
I had to change the mergeEntity
function in the following way:
将第13334行更改为:
Change line 13334 from:
if (targetEntity) {
到
if (targetEntity && ! (meta.FetchAsDetached == true)) {
在第13380行附近添加附加条件,如有必要,跳过附加实体:
Add additional condition around line 13380, to skip over attaching the entities if necessary:
if (!(meta.FetchAsDetached == true)) { // attach only if necessarry
attachEntityCore(em, targetEntity, EntityState.Unchanged);
targetEntity.entityAspect.wasLoaded = true;
em.entityChanged.publish({ entityAction: EntityAction.AttachOnQuery, entity: targetEntity });
}
这使我能够从处于分离状态的服务器中获取潜在的新实体。后来,我能够将它们添加到 EntityManager
中,并且将它们正确插入到数据库中作为新记录。
This enables me to fetch the potential new entities from server in detached state. Later, I was able to add them to were EntityManager
and they wre correctly inserte dinto the databaes as new records.
这也解决了轻而易举的问题,因为轻而易举地将两个不同的项目(都具有未初始化的密钥)视为同一项目,因为它期望它们具有现有的唯一密钥。
This also solves the problem with breeze treating two different items (both with non-initialized key) as the same one, becaue it expects' that they have existing unique keys.
这篇关于如何使用breezejs从服务器获取新的(EntityState.New)实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!