1

我在ASP.NET MVC 4 SPA和durandal項目中使用breezejs(帶有EF 5.0數據庫的第一個安裝程序),除了特定場景外,事情正常運行。使用Breezejs捕獲SaveChanges上的外鍵異常()

請原諒我,如果我對JavaScript和SPA的東西看起來有些不爽。我正在學習。

這裏是我從EF

2款

Project.cs

public partial class Project 
{ 
     public Project() 
     { 
      this.Timesheets = new HashSet<Timesheet>(); 
     } 

     public int ProjectId { get; set; } 
     public Nullable<int> ClientId { get; set; } 
     public string ProjectName { get; set; } 
     public string ProjectDescription { get; set; } 
     public Nullable<decimal> ProjectRate { get; set; } 

     public virtual Client Client { get; set; } 
     public virtual ICollection<Timesheet> Timesheets { get; set; } 
} 

Client.cs

public partial class Client 
{ 
    public Client() 
    { 
     this.Projects = new HashSet<Project>(); 
     this.Timesheets = new HashSet<Timesheet>(); 
    } 

    public int ClientId { get; set; } 
    public string ClientNo { get; set; } 
    public string ClientName { get; set; } 
    public string CompanyName { get; set; } 
    public string AddressLine1 { get; set; } 
    public string AddressLine2 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Zip { get; set; } 
    public string County { get; set; } 
    public Nullable<decimal> ClientRate { get; set; } 
    public string EmailAddress { get; set; } 

    public virtual ICollection<Project> Projects { get; set; } 
    public virtual ICollection<Timesheet> Timesheets { get; set; } 
} 

從我的客戶視圖模型

function deleteClient(model) { 
    app.showMessage('Are you sure you want to DELETE this record?', 'Delete a Record', ['Yes', 'No']) 
    .then(function (dialogresult) { 
     if (dialogresult == "Yes") { 
      models.remove(model); 
      model.entityAspect.setDeleted(); 
      return saveRecord(model); 
     } 
    }); 
}; 

function saveRecord(model) { 
    return repository.saveEntity(model) 
    .fail(handleFailed); 

    function handleFailed(error) { 
     var err = "Error retrieving Clients : " + error.message; 
     error(err); 
     logger.error(err, null, null, true); 
     return; 
    } 
}; 

摘錄的摘錄repository.js( DataContext的)

function saveEntity(masterEntity) { 
    return manager.saveChanges().fail(saveFailed); 

    function saveFailed(error) { 
      logger.error("Error saving : " + error.message, null, null, true); 
    } 
} 

這裏是摘自我的ProjectBillingController.cs

[HttpPost] 
    public SaveResult SaveChanges(JObject saveBundle) 
    { 
     return _contextProvider.SaveChanges(saveBundle); 
    } 

這裏是我的情況下,

我有一個行項目 「P1」 具有參考客戶 「ABC」 。如果我嘗試刪除客戶端「ABC」,breeze會在我的WEBAPI控制器「ProjectBillingController.cs」的SaveChanges內引發異常。

我知道,在SQL世界中,這應該是預期的錯誤。

但我的問題是...

  • 我可以捕獲客戶端上的這一約束錯誤它獲取到服務器「ProjectBillingController.cs」過嗎?
  • 我看到解決此問題的唯一方法是執行另一個查詢,以查看是否存在具有該客戶端的Project實體中的任何行,如果是這樣,則暫停刪除,否則繼續刪除。有沒有另外一種方法來完成這個?
  • 我應該寫這個「驗證邏輯」我的視圖模型裏面,或者datacontent(資料庫)
+0

我的歉意,我似乎已經解決了這個問題。我的問題是我在我的logger.error()方法中有一個錯字。它應該是logger.logError()。正因爲如此,這個錯誤並沒有被返回給客戶,而是給出了一個模糊的信息。當我通過調試運行它時,我看到外鍵約束的異常,並認爲它沒有返回到客戶端。一旦我改變了名字。該錯誤返回到saveChanges()承諾的.failed()部分,我能夠看到該錯誤。 – 2013-03-16 01:18:36

回答

1

在項目的表格屬性,你應該有客戶權利FK關係?在這種關係中,刪除規則應設置爲CASCADE(請注意,這將刪除客戶端時刪除所有客戶端的相關項目)。

所以,一步一步: 1.在Visual Studio中,檢查服務器資源管理器 2.右擊表「項目」 3.選擇「表格屬性」

檢查什麼我提到關於刪除規則,並相應地改變它。

蒂亞戈

+0

感謝您的建議,但在事件中,用戶嘗試刪除具有與其關聯的項目的客戶端,我不想允許這樣做。 – 2013-03-16 00:37:17

1

我不相信有一種方法來檢測客戶端上,刪除家長應該級聯刪除的任何兒童相關的實體。在調用服務器之前,您無法捕獲「錯誤」。您可以在客戶端進行賠償......如下所述。

我認爲我更喜歡蒂亞戈的建議,即將數據庫(和/或EF)配置爲自動級聯刪除。

如果這不可行,您可以在客戶端或服務器上以編程方式處理它。您可以下載子實體(或只是他們的密鑰),並在刪除父實體時將其刪除。或者你也可以在你的控制器的服務器上(或者更好的是,在服務器上的輔助類中)。這些是更乏味的選擇,有時可能是必要的。

如果您在客戶端寫入邏輯,請在您的「datacontext」中執行此操作。這不是ViewModel的問題。

FWIW,我不會稱之爲「驗證邏輯」。你沒有驗證數據。驗證邏輯從不改變數據;它只能讀出有效或無效的數據。

您正在根據業務模型規則操作數據,該規則說明在刪除父項時必須刪除此父項EntityType實例的子項。這條規則並沒有什麼內在的明顯之處。從架構角度來看,「顏色」是產品類型的「父」,因爲它與產品具有一對多關係。但是,如果我刪除了「紅色」顏色,我不希望所有紅色產品都被自動刪除。由於級聯刪除本質上是危險的,因此您必須竭盡全力配置服務器組件來支持它。

刪除是一個討厭的業務。就我個人而言,如果可以的話,我避免在我的應用程序中刪除,而是使用某種形式的軟刪除。我承認這並不總是一種選擇。

+0

感謝您的輸入。我同意如果刪除「紅色」顏色,我不希望所有「紅色產品」都被刪除。如果我用名爲「HasProjects」的計算字段擴展客戶端實體,如果這是真的,我將通過knockoutjs禁用html上的刪除按鈕。 – 2013-03-16 00:39:47

+0

你可以這樣做。這是否是正確的應用程序行爲?如果你想能夠刪除父母和孩子呢?還要注意,如果你知道「HasProjects」的答案,那麼它是因爲你以某種方式查詢「項目」(或者他們的存在)。完成這麼多工作後,無論如何都可以輕鬆地從客戶端刪除父母和孩子。只要記得在父節點上設置「setDeleted」時迭代子節點和'setDeleted'節點。 – Ward 2013-03-16 16:45:32

+0

N.B .:甚至客戶端刪除子項可能會在服務器上失敗......如果不同用戶在當前用戶準備刪除父項時添加/刪除了有問題的父項子項。現在我們正在討論聚合根上的併發檢查......另一個重要主題。如果一切都像看起來一樣簡單,那不是很好嗎? :) – Ward 2013-03-16 16:47:34