使用Breezejs捕获SaveChanges上的外键异常()

时间:2013-03-15 21:03:06

标签: asp.net asp.net-web-api breeze single-page-application durandal

我在ASP.NET MVC 4 SPA和durandal项目中使用breezejs w / EF 5.0数据库首次设置,除了某种情况外,工作正常。

请原谅我,如果我看起来有点像javascript和SPA的东西。我正在学习。

这是我的2个EF模型

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);
    }

这是我的方案,

我有一排Project&#34; P1&#34;它引用了客户&#34; ABC&#34;。如果我试图删除客户端&#34; ABC&#34; breeze在我的WEBAPI控制器&#34; ProjectBillingController.cs&#34;中的SaveChanges内部抛出异常。

我知道在SQL世界中,这应该是预期的错误。

但我的问题是......

  • 我可以在到达服务器之前在客户端捕获此约束错误&#34; ProjectBillingController.cs&#34;?
  • 我看到解决此问题的唯一方法是执行另一个查询以查看Project实体中是否有任何行与该客户端,如果是,则停止删除,否则继续删除。还有另一种方法可以实现这个目标吗?
  • 我应该写这个&#34;验证逻辑&#34;在我的viewmodel或datacontent(存储库)

2 个答案:

答案 0 :(得分:1)

在Project的表属性上,您应该与客户端建立FK关系吗?在此关系上,删除规则应设置为CASCADE(请注意,这将删除客户端时删除所有客户端的相关项目。)

所以,一步一步: 1.在Visual Studio中,检查“服务器资源管理器” 2.右键单击表“项目” 3.选择“表格属性”

检查我提到的有关删除规则的内容,并相应地进行更改。

蒂亚戈

答案 1 :(得分:1)

我不相信有一种方法可以在客户端上检测到删除父级应该将删除级联删除到任何与子级相关的实体。在调用服务器之前,您无法捕获“错误”。您可以在客户端上进行补偿......如下所述。

我认为我更喜欢Tiago的建议,即将数据库(和/或EF)配置为自动级联删除。

如果无法做到这一点,您可以在客户端或服务器上以编程方式处理它。您可以下载子实体(或只是他们的键),并在删除父项时在客户端上删除它们。或者你可以在控制器的服务器上(或者更好,在服务器上的辅助类中)。这些是有时需要的更乏味的替代方案。

如果您在客户端上编写逻辑,请在“datacontext”中执行此操作。这不是ViewModel关注的问题。

FWIW,我不会称之为“验证逻辑”。您没有验证数据。验证逻辑永远不会改变数据;它只能发布有效或无效的数据。

您正在根据业务模型规则对数据进行操作,该规则指出在删除父项时必须删除此父EntityType实例的子项。这条规则没有任何内在明显的证据。从架构的角度来看,“颜色”是产品类型的“父”,因为它与Product具有1对多的关系。但是,如果我删除了“红色”颜色,我不希望自动删除所有红色产品。由于级联删除本质上是危险的,因此您必须尽量配置服务器组件以支持它。

删除是一项讨厌的事情。就个人而言,我可以避免在我的应用程序中删除,如果可以的话,可以使用某种形式的软删除。我承认这并不总是一种选择。