带服务的MVC存储库模式 - 如何在DAL上获取错误?

时间:2013-04-29 15:07:53

标签: asp.net-mvc entity-framework repository-pattern

所以我的服务中有一个方法,我将从控制器调用:

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?
    }

修改

所以问题不在于让我的代码工作,而是使用存储库模式时遇到的问题,同时使用服务层作为“介于”之间用于 DAL 演示文稿

之间的通信

所以我有一个名为DataLibrary的单独程序集。

DataLibrary包含我的模型(Message),我的存储库和服务(MessageService

在我的MVC网站中,我通常会有一个具有CRUD功能的控制器。它看起来像这样:

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

但是通过使用存储库模式,通过服务层进行通信,我改为:

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

我如何知道操作成功或不成功以及出于什么原因?

如何在上述同时从服务的业务逻辑中检索填充的数据?

我如何在尽可能接近MVC设计模式/关注可扩展性的问题的同时实现上述两个目标?

3 个答案:

答案 0 :(得分:0)

您确实没有提供有关您的架构的足够信息,以便回答这个问题。但是,如果您想从SendMessage方法获取值,则添加返回值而不是void是一个很好的起点。

答案 1 :(得分:0)

首先,如果只是将工作委托给您的存储库,为什么要通过服务?如果您已正确实现了存储库(即完全抽象),则无需使用该服务。只需直接从控制器调用存储库即可。您可以在我的blog中了解有关存储库模式的更多信息。

但这并没有真正解决这个问题。

那么你如何处理错误?当遇到异常时:Simply do not catch it;)Exceptions are after all exceptions并且您通常无法处理以提供预期结果。

正如我们所说的那样,数据层通常意味着一个稳定的数据库引擎,预计读/写将成功。因此,除了使用异常之外,不需要任何其他错误处理。

在ASP.NET MVC中,您可以使用属性处理事务,并使用try / catch填充模型状态,如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);
    }
}

答案 2 :(得分: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");
     }
}

如上所述,控制器和服务层方法可以共享彼此的对象。它们彼此有界限,它们相互耦合。但是你的架构决定了它们的耦合程度。

您也可以单向执行这些映射。像服务器只有控制器或控制器只服务。如果您不想在服务层中使用viewmodel,则应始终在服务层中进行映射。否则在控制器中进行对象映射。而且也不要忘记将你的viewmodel放到另一个库中,这非常重要。这些就像“价值对象”。