2013-04-29 60 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? 
    } 

编辑:

所以,问题是不是真正的让我的代码工作这是个问题我与存储库模式同时使用服务层作为“之间走”通信的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设计模式/关注可扩展性的前提下,如何实现上述两者?

+0

为了澄清,服务层,回购和DTO包装在一个单独的程序集内。 – Smithy 2013-04-29 15:08:24

回答

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

我读过你的博客文章,我有类似的问题,那里的第一张海报。我有业务逻辑,我觉得应该进入一个服务层,因为我需要在一个地方(控制器除外)使用refs到各种模型/回购站。如果我插入一个用户,我该如何返回'用户已存在的错误'? – Smithy 2013-04-29 20:37:56

+1

抛出一个异常 – jgauffin 2013-05-03 07:48:35

+0

现在总体感觉,我很抱歉迟到的回应。如果它的工作返回对象,否则我可以抛出并捕获我自己的错误内部和验证对此:) – Smithy 2013-05-17 22:43:36

0

你真的没有提供足够的关于你的架构的信息来构建回答这个问题。但是,如果您想从SendMessage方法中获得一个值,则添加一个返回值而不是void是一个很好的开始。

+0

哈哈。好的回应。我正在寻找一些理论,然后我可以去研究。我希望我的编辑能够说明我在找什么。 – Smithy 2013-04-29 19:54:33

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放到另一个库中,这非常重要。这些就像“价值对象”。