2013-04-29 4 views
0

Так у меня есть метод в моей службы, которые я буду называть из контроллера:Шаблон MVC-репозитория с сервисами - как получить ошибки в DAL?

public void SendMessage(Message message) { 
     message.Property = "Random"; 
     try { 
      // try some insert logic 
     } 
     catch (Exception) { 
      // if it fails undo some stuff 
      // return the errors 
      throw; 
     } 

     // if there are no errors on the return the operation was a success 
     // but how do I get the Service generated data? 
    } 

Edit:

Так что вопрос на самом деле не о том, чтобы мой код, чтобы работать, это проблема у меня есть с Repository Pattern в то время как с помощью Service Layer как «идти между» для общения между DAL и Презентация

Итак, у меня есть отдельная сборка под названием DataLibrary.

DataLibrary имеет свои модели (Message), мои репозиториев и услуги (MessageService)

В моем сайте MVC я обычно есть контроллер, с функциональностью CRUD. Это будет выглядеть примерно так:

public ActionResult Create(Message message) { 
    if(ModelState.IsValid) { 
     db.insert(message); 
    } 
    Return View(message); 
} 

Но с помощью Repository Pattern, с сервисным слоем для общения у меня есть это вместо:

public ActionResult Create(MessageCreateModel message) { 
    if(ModelState.IsValid) { 
     MessageService.SendMessage(message.ToDTO()); 
    } 
    Return View(message); 
} 

Как я знаю, что операция была успешной или неудачной и по какой причине?

Как получить заполненные данные из бизнес-логики службы в то же время, что и выше?

И как мне достичь обоих этих двух выше, приклеиваясь как можно ближе к шаблону проектирования MVC/spearation проблем для расширяемости?

+0

Чтобы уточнить, сервисный уровень, репозитории и DTO завернуты внутри отдельной сборки. – Smithy

ответ

0

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

Но это действительно не касается проблемы.

Итак, как вы обрабатываете ошибки? Когда дело доходит до исключений: Simply do not catch it;) Exceptions are after all exceptions и это не то, что вы обычно можете обработать, чтобы доставить ожидаемый результат.

Как мы говорим о слое данных, который обычно означает стабильный механизм базы данных, где ожидается, что чтение/запись будет успешным. Следовательно, нет необходимости в какой-либо другой обработке ошибок, чем использование исключений.

В ASP.NET MVC вы можете обрабатывать транзакции с атрибутом и использовать попытаться/поймать, чтобы заполнить состояние модели, как показано here:

[HttpPost, Transactional] 
public virtual ActionResult Create(CreateModel model) 
{ 
    if (!ModelState.IsValid) 
     return View(model); 

    try 
    { 
     model.Category = model.Category ?? "Allmänt"; 

     var instruction = new Instruction(CurrentUser); 
     Mapper.Map(model, instruction); 
     _repository.Save(instruction); 

     return RedirectToAction("Details", new {id = instruction.Id}); 
    } 
    catch (Exception err) 
    { 
     // Adds an error to prevent commit. 
     ModelState.AddModelError("", err.Message); 
     Logger.Error("Failed to save instruction for app " + CurrentApplication, err); 
     return View(model); 
    } 
} 
+0

Я прочитал ваше сообщение в блоге, у меня есть аналогичная проблема с первым плакатом. У меня есть бизнес-логика, я чувствую, что должен перейти на сервисный уровень, потому что мне нужно использовать refs для разных моделей/репозиториев в одном месте (кроме контроллера). Если я вместо этого вставляю пользователя, как мне вернуть «Пользователь уже существует ошибка»? – Smithy

+1

Бросить исключение – jgauffin

+0

Делает теперь полный смысл, мои извинения за поздний ответ. если он работает, возвратите Object, иначе я могу бросить и поймать собственные ошибки внутри себя и проверить на это :) – Smithy

0

Вы действительно не предоставили достаточной информации о своей архитектуре, чтобы ответить на этот вопрос. Однако, если вы хотите получить значение обратно из метода SendMessage, добавление возвращаемого значения вместо void - хорошее место для начала.

+0

Ха-ха. Хороший ответ. Я искал немного теории, чтобы потом уйти и исследовать. Надеюсь, мое редактирование пролило свет на то, что я ищу. – Smithy

0

Я думаю, вы должны сначала решить, как вы собираетесь разрабатывать архитектуру. Вы идете с ориентированной на обслуживание, если так, ваши методы обслуживания должны возвращать что-то для информационных контроллеров. Поэтому подумайте, что ваш уровень обслуживания, как граница страны, и границы другой страны - это контроллеры. И вы должны разрешить торговлю этими двумя странами. Это можно сделать с помощью возвращаемого объекта, который содержит данные о возврате, а также ошибки обслуживания и т. Д.

Если вы хотите разместить свою бизнес-логику в своем сервисе, то вам, вероятно, не нужны независимые слои. Для вас достаточно немного свободного сцепления. Таким образом, вы можете возвращать базовые объекты clr или объекты домена или объекты приложения. В очень базовом примере вот так:

//AService service method 
public AnEntity ServiceMethod(AFilterViewModel aFilter) 
{ 
    //do some validation 
    try 
    { 
      //some transactional operations 
    } 
    catch 
    { 
      //do some log and rollback it... 
      throw; 
    } 
    var anEntity = _aRepository.GetSomeEntity(x=> x.Something == aFilter.Something); 
    return anEntity; 
} 

//controller method 
public ActionResult GetSomething(AFilterViewModel aFilter) 
{ 
    try 
    { 
      var entity = _aService.ServiceMethod(aFilter); 
      AViewModel model = MapToView(entity); 
      return View(model); 
    } 
    catch 
    { 
      return RedirectToAction("Error"); 
    } 
} 

Как вы видите выше, методы контроллера и уровня сервиса могут совместно использовать объекты друг друга. У них есть границы друг с другом, и они сочетаются. Но ваша архитектура решает, насколько они связаны.

Вы также можете выполнять эти сопоставления только в одну сторону. Что-то вроде обслуживания только Controller или Controller только для обслуживания. Если вы не хотите использовать свою модель просмотра в уровне обслуживания, вы всегда должны делать сопоставления на уровне сервиса. В противном случае сделайте сопоставление объектов в контроллерах. А также не забыл поместить ваш viewmodel в другую библиотеку, что очень важно. Это что-то вроде «объектов ценности».

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