2

我在 ASP.NET MVC 4 SPA 和带有 EF 5.0 数据库的 durandal 项目中使用了微风,除了某些情况外,一切正常。

如果我在 javascript 和 SPA 方面看起来有点菜鸟,请原谅我。我边走边学。

这是我的 2 个 EF 模型

项目.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; }
}

客户端.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(数据上下文)

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

这是我的场景,

我有一个对客户“ABC”的引用的项目“P1”。如果我尝试删除客户端“ABC”,微风会在我的 WEBAPI 控制器“ProjectBillingController.cs”的 SaveChanges 内引发异常。

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

但我的问题是...

  • 我可以在客户端到达服务器“ProjectBillingController.cs”之前捕获此约束错误吗?
  • 我认为解决此问题的唯一方法是进行另一个查询,以查看该客户端的 Project 实体中是否有任何行,如果有,则停止删除,否则继续删除。还有另一种方法可以做到这一点吗?
  • 我应该在我的视图模型或数据内容(存储库)中编写这个“验证逻辑”吗
4

2 回答 2

1

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

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

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

蒂亚戈

于 2013-03-15T22:35:39.240 回答
1

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

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

如果这不可能,您可以在客户端或服务器上以编程方式处理它。您可以下载子实体(或仅它们的密钥)并在删除父实体时在客户端上删除它们。或者,您可以在控制器中的服务器上使用相同的方法(或者,更好的是,在服务器上的辅助类中)。这些是有时可能需要的更繁琐的替代方案。

如果您在客户端编写逻辑,请在您的“数据上下文”中进行。这不是 ViewModel 关心的问题。

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

您正在根据业务模型规则对数据进行操作,该规则说在删除父实体时必须删除此父实体类型实例的子实体。这条规则本质上没有什么明显的。从模式的角度来看,“颜色”是产品类型的“父级”,因为它与产品具有一对多的关系。但是,如果我删除了“红色”颜色,我不希望我的所有红色产品都被自动删除。因为级联删除本质上是危险的,所以您必须不遗余力地配置服务器组件以支持它。

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

于 2013-03-15T23:31:55.693 回答