1

Я использую breezejs в ASP.NET MVC 4 SPA и durandal project с EF 5.0. Сначала база данных базы данных, и все работает нормально, за исключением определенного сценария.с использованием Breezejs для захвата исключения внешнего ключа в SaveChanges()

Простите меня, если я кажусь чем-то вроде noob относительно 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; } 
} 

отрывок из моего клиента ViewModel

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», бриз выдает исключение внутри SaveChanges в моем WEBAPI-контроллере «ProjectBillingController.cs».

Я знаю, что в этом мире SQL это должна быть ожидаемая ошибка.

Но мои вопросы ...

  • Могу ли я захватить эту ошибку ограничения на стороне клиента, прежде чем он доберется до сервера «ProjectBillingController.cs»?
  • Единственный способ, с помощью которого я разрешаю эту проблему, - сделать еще один запрос, чтобы увидеть, есть ли какие-либо строки в объекте Project с этим Клиентом, и если это прекратить удаление, в противном случае продолжить удаление. Есть ли другой способ сделать это?
  • Если я пишу это «Validation логики» внутри моей ViewModel или datacontent (хранилище)
+0

Мои извинения, я, кажется, решил эту проблему. Моя проблема заключалась в том, что у меня была опечатка в моем методе logger.error(). Это должно быть logger.logError(). и из-за этого ошибка не возвращалась клиенту, она давала неопределенное сообщение. Когда я запускал его через debug, я видел исключение из ограничения внешнего ключа и думал, что он не возвращается к клиенту. Как только я изменил имя. ошибка возвращалась в .failed() часть обещания saveChanges(), и я могу видеть ошибку. –

ответ

1

О свойствах таблицы проекта, вы должны иметь отношение FK с Клиентом правом? В этом отношении правило удаления должно быть установлено в CASCADE (обратите внимание, что это удалит все связанные проекты Клиента при удалении Клиента).

Так, шаг за шагом: 1. В Visual Studio, проверьте Проводник сервера 2. Щелкните правой кнопкой мыши таблицу «Проект» 3. Выберите «Свойства таблицы»

Проверьте, что я говорил о правило удаления , и соответственно изменить его.

Tiago

+0

Благодарим вас за предложение, но в случае, когда пользователь пытается удалить клиента, у которого есть связанные с ним проекты, я не хочу этого допускать. –

1

Я не верю, что есть способ обнаружения на клиенте, что удаление родителя должно каскадное удаление любых лиц, связанных с детьми. Вы не можете поймать «ошибку» перед вызовом сервера. Вы можете компенсировать клиенту ... как описано ниже.

Я думаю, я предпочитаю, чтобы Тьяго предложил автоматически настроить вашу базу данных (и/или EF) на автоматическое удаление каскада.

Если это невозможно, вы можете обращаться с ним программно на клиенте или сервере. Вы можете загрузить дочерние объекты (или только их ключи) и удалить их на клиенте при удалении родителя. Или вы можете на сервере в своем контроллере (или, что еще лучше, в вспомогательном классе на сервере). Это более утомительные альтернативы, которые иногда могут потребоваться.

Если вы напишете логику на клиенте, сделайте это в своем «datacontext». Это не проблема ViewModel.

FWIW, я бы не назвал эту «логику проверки». Вы не проверяете данные. Логика проверки никогда не изменяет данные; он может только объявлять данные действительными или недействительными.

Вы работаете с данными в соответствии с правилом бизнес-модели, в котором говорится, что дети экземпляров этого родительского EntityType должны быть удалены при удалении родителя. В этом правиле нет ничего очевидного. С точки зрения схемы «Цвет» является «родителем» типа «Продукт», поскольку он имеет отношение «1 ко многим» к «Продукту». Но, если я удалю цвет «Красный», я бы НЕ хотел, чтобы все мои красные продукты были удалены автоматически. Поскольку каскадное удаление по своей сути опасно, вы должны уйти от своего пути, чтобы настроить серверные компоненты для его поддержки.

Удалить неприятный бизнес. Лично я избегаю удаления в своих приложениях, если могу, и вместо этого использую какую-то форму мягкого удаления. Я признаю, что это не всегда вариант.

+0

Спасибо за ваш вход. Я согласен, что не хочу, чтобы все мои «красные продукты» удалялись, если я удаляю «красный» цвет. Что делать, если я расширяю объект Client с вычисленным полем «HasProjects», и если это правда, я отключу кнопку удаления на html через knockoutjs. –

+0

Вы могли бы это сделать. Это будет правильное поведение приложения? Что делать, если вы хотите удалить родительские и дочерние элементы? Заметим также, что если вы знаете ответ на «HasProjects», это потому, что вы как-то спросили «Проекты» (или их существование). Сделав так много, вы можете так же легко удалить родительские и дочерние элементы из клиента. Просто помните, чтобы перебирать детей и 'setDeleted' на них, когда вы' setDeleted' на родительском. – Ward

+0

N.B .: даже удаление на стороне клиента на компьютере может потерпеть неудачу на сервере ... если другой пользователь добавил/удалил дочерние элементы родителя, о котором идет речь, пока текущий пользователь готовится удалить родителя. Теперь мы попадаем в тему проверки параллелизма в сводном корне ... другая важная тема. Было бы неплохо, если бы все было так же просто, как кажется? :) – Ward

Смежные вопросы