如何使用breezejs从服务器获取新的(EntityState.New)实体 [英] How to fetch new (EntityState.New) entities from server with breezejs

查看:52
本文介绍了如何使用breezejs从服务器获取新的(EntityState.New)实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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.

详细信息:


  1. 客户端使用搜索条件作为方法参数调用服务器。服务器方法返回 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 Added 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆