2013-08-29 37 views
0

我有一個Web服務返回一些數據,然後將其轉換爲服務器上的新實體,然後傳遞給客戶端,用戶可以在其中編輯它們。如果他選擇SaveChanges,則應將實體提交給服務器並插入到數據庫中。我有兩個問題:如何使用breezejs從服務器獲取新的(EntityState.New)實體

  • 當實體返回到客戶端,微風將其標記爲EntityState.New
  • 微風預期,即不變實體具有主鍵設置。因爲沒有返回的新實體的具有按鍵(類型的鍵值的Int32等於0),微風認爲,服務器返回的同一實體

的多個實例,爲了說明問題,改變ToDosController.ToDos AngularJS樣品中的方法來匹配以下:

[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(我不想這樣做,因爲這些密鑰是由數據庫生成的),但問題沒有表現出來。

問題:如何正確地從服務器返回實體,以便它們將被標記爲EntityState.New,當調用SaveChanges時,它們將被保存到數據庫(使用生成的密鑰)。

我期望客戶端上的一些MergeStrategy或服務器上的一些額外的數據/屬性來實現這一點,但無法找到一個。

UPDATE:

澄清:

我盡力支持的方案時,用戶選擇和編輯從其他來源起源的實體之一,這應該是後來添加到我的數據庫。

在細節:

  1. 客戶端調用與搜索條件方法參數的服務器。服務器方法返回IEnumerable<Customer> - 它返回IQueriable<Customer>

  2. 服務器查詢後端Web服務(CRM系統)和後端網絡服務的結果轉換成Customer實體。結果返回給客戶端。後端Web服務不可用於客戶端。

  3. 客戶端顯示結果給用戶

  4. 用戶選擇的實體之一和編輯其屬性(如變更顧客的姓名或地址)

  5. 所選客戶被添加到實體管理器上客戶端。它應該是在EntityState.Added

  6. em.SaveChanges被調用時,它提交Add版實體

  7. 服務器插入新客戶到數據庫服務器,數據庫生成新的主鍵,這是返回給客戶端,其中EM更新的實體按鍵,並設置實體狀態EntityState.Unchanged

也許我需要分離的實體和正確的問題是:「如何實體返回給客戶端無需插件把他們交給實體經理?「(它們將在上面的步驟5中添加)。

P.S: 一個解決方案是使用自定義的非實體數據類型(如CustomerFromCRM)作爲我的服務器方法的結果。然後,我會將它們轉換爲客戶端上的實體Customer。但我想避免創建額外的類。

UPDATE2:我發現了一個類似的問題(有沒有公認的answere)位置:is there an easy way to mark an entity in the cache as "added"?

回答

0

回答我的questiosn:

我能夠在某種程度上改變微風源代碼得到這個工作,如果指定的標誌設置不重視實體EntityManager。我可以定義自定義MergeStreategy,但由於我不想在微風代碼中混淆枚舉,因此我定義了自定義實現JsonResultAdapter.visitNode方法返回的對象上的自定義字段FetchAsDetached

我不得不改變mergeEntity功能通過以下方式:

更改線路13334來源:

if (targetEntity) { 

if (targetEntity && ! (meta.FetchAsDetached == true)) { 

添加周圍線13380附加條件,跳過如有必要附加實體:

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,他們將正確插入數據庫作爲新記錄。

這也解決了微風將兩個不同項目(都與非初始化密鑰)作爲同一個項目的問題,因爲它期望'他們有現有的唯一密鑰。

1

沒有因爲EntityState.New這樣的事情。 當您在客戶端上創建新實體並將其添加到EM時,EntityState將下注設置爲已添加。一旦調用em.SaveChanges,新的實體將被保存在數據庫中,並且其EntityState將更新爲未更改。 如果查詢數據,服務器將返回EntityState.Unchanged的實體。如果您對這些實體中的任何一個進行更改,EntityState將設置爲修改(如果更新)或刪除(如果您調用EntityAspect.setDeleted)。

在你的代碼片段中,你只是返回2個對象。它們尚未保存到數據庫中,因此沒有鍵值已經設置。

這是對你的問題正是你正在嘗試做的不清楚......

  • 你們是不是有一些初步的數據一起工作呢?如果是這樣,你應該種下你的數據庫。
  • 你只是想創建新的實體嗎?如果是這樣,你爲什麼要在服務器上做它?你應該在客戶端上做。

var todoItem1 = em.createEntity("TodoItem", { description: "First Item" }); 
var todoItem2 = em.createEntity("TodoItem", { description: "Second Item" }); 

編輯:

您的情況目前還不清楚我的,但這裏的達到自己的目標的解決方案:

1一定要手動添加一個臨時ID給你的實體(temp ID必須是唯一的):

[HttpGet] 
public IEnumerable<TodoItem> Todos() { 
    return new TodoItem[] { 
     new TodoItem() { Id=-1001, Description="First item"}, 
     new TodoItem() { Id=-1002, Description="Second item"} 
    }; 
} 

2-您將會注意到這些實體將擁有EntityState。不變的客戶端,讓你脫離他們:

var todoItem1 = data.results[0]; 
var todoItem2 = data.results[1]; 
todoItem1.entityAspect.setDetached(); 
todoItem2.entityAspect.setDetached(); 

3-現在你可以操縱他們,你想,如果你決定保存它們,將它們添加到經理作出的SaveChanges打電話之前:

manager.addEntity(todoItem1); 
manager.addEntity(todoItem2); 
manager.saveChanges(); 
+0

感謝您的回答。 1)你是對的,沒有'EntityState.New'。 2)我已經更新了這個問題來澄清情況。 3)我不能爲我的數據庫輸入初始數據,因爲數據來源於外部數據源(數據庫中尚未存在)。 4)我無法在客戶端創建新實體,因爲我沒有關於它們的數據。上面的代碼示例只是爲了說明 - 它包含常量而不是調用後端Web服務並將結果轉換爲實體。 – matra

1

我想我明白了。外部服務提供潛在新實體的數據。顯而易見的是將這些數據作爲客戶以外的其他類型發送,可能是匿名類型;有趣的是,你在製作Customer對象的服務器上遇到了麻煩;何必?

無論如何,您將採用這些非客戶數據並按照您提出的方式在客戶端上創建新客戶。

如果您的心在使用服務器上的客戶類型時設置,您可以編寫定製的JasonResultsAdapter,以便在查詢時清除數據(清除每個節點上的$類型)時不緩存數據。僅對此查詢使用此適配器

但首先我會重新考慮爲什麼你把他們作爲客戶發送,因爲他們真的不是。

+0

是的,你知道了;-)我實際上是從不同的數據源(客戶,客戶地址,客戶賬戶......)在服務器上構建一個對象圖。我不能在客戶端做到這一點。引入額外的非實體類並將它們映射到客戶端上將是很多工作。非常感謝您提供關於使用'JSonResultAdapter'的建議,但是當我嘗試向EM添加實體時,它在步驟5(上面)中失敗。它在checkEntityType的第二行失敗,因爲entity.prototype是未定義的。 – matra

+0

順便說一句:樣品http://www.breezejs.com/sites/all/apidocs/classes/JsonResultsAdapter.html有一個錯誤。 'normalizeTypeName'調用應該以'breeze.MetadataStore'爲前綴。 – matra