【问题标题】:Asp MVC solution structureAsp MVC解决方案结构
【发布时间】:2015-12-15 13:18:07
【问题描述】:

我刚刚开始使用 MVC,并选择让我的解决方案为数据库交互和一个 UI 项目分别保存一个项目(希望是一种可接受的工作方式)。 UI 引用了 BL,但 BL 没有对 UI 的引用。因此,我必须将参数设置为dynamic(下面的示例)才能将值传递给 BL,是否应该避免这种情况?如果是,为什么?(除了缺乏智能感知)。

public class MyController : Controller
{
    [HttpPost]
    public ActionResult MyAction(MyActionViewModel vm)
    {
        if (!ModelState.IsValid)
        {
            return View(vm);
        }

        //pass formCollection to model to do stuff with
        int isSuccessful = ModelName.Insert(vm);
        return RedirectToAction(....);
    }
}

public partial class ModelName
{
    public static int Insert(dynamic theVm)
    {
        using (ModelEntities ctx = new ModelEntities ())
        {
            ModelName mn= new ModelName();
            mn.AddressLineOne = theVm.AddressLineOne;
            mn.AddressLineTwo = theVm.AddressLineTwo;

            ctx.TheTargetedEntity.Add(mn);
            ctx.SaveChanges();
            return mn.id;
        }
    }
}

一位同事建议我应该做一个额外的项目,让 BL 和 UI 都引用,这样我就可以对我传递的参数进行强类型化(并尽可能避免弱类型化)。我的问题是,在这种情况下,它似乎在解决方案中引入了不必要的元素。

我是在以一种过于简单的方式看待这个问题,还是这个建议使问题过于复杂,或者我们都完全错过了一些东西(我们都是 MVC 的新手,来自 Web 表单,网站将是中小型网站)。

【问题讨论】:

  • 在POST方法中,初始化数据模型的一个实例,并将视图模型属性映射到它,然后保存数据模型。
  • 那不会让我的控制器“变胖”吗?我读过也应该避免。
  • 我绝对会建议和你的同事一样,我认为very bad 实践使用dynamic 用于BL 公共API。不知道为什么你认为这是不必要的 - 你仍然会在 BL 和 UI 之间有很强的解耦。
  • 当然不是。至于“胖”与“瘦”控制器 - 这是一个见仁见智的问题。但不好的做法是使用动态并在模型内部访问数据库
  • 谢谢。我可能会听从同事的建议

标签: c# asp.net-mvc entity-framework architecture entity-framework-6


【解决方案1】:

我认为与其将动态传递给 BLL,不如为您的模型创建一个项目并将您的模型放在那里,这样模型库可以在 UI 和 BLL 之间共享,而不会违反任何规则,也不会使 BLL 依赖于 UI .

使用动态,你会错过的不是智能感知,而是打字工作。

项目结构如下:

  • 模型项目(独立,仅包含模型)
  • BLL 项目(有模型的引用,包含数据访问和业务逻辑)
  • UI 项目(有 BLL 的引用,有模型的引用,包含 ViewModels、Controllers、Views)

从技术上讲,模型项目可以在不违反规则的情况下合并到 BLL 中,但是将它们放在单独的程序集中有其好处。

您应该在时间、预算、项目规模等之间进行权衡,以做出正确的决定。但一开始,这 3 层就足够了(而您可以将主题减少到 2 层)。

【讨论】:

    【解决方案2】:

    你的 BL 项目应该对 UI 一无所知,没错。我认为使用动态不是一个好主意。您应该将 ViewModel 对象转换为 BL 对象。你可以用 AutoMapper 来做http://automapper.org/

    【讨论】:

      【解决方案3】:

      我认为您应该放弃使用动态并使用更严格的定义参数。首先,当其他人阅读您的代码和编写单元测试时,它会让您的意图更加清晰。

      如果您知道要插入哪个实体,则可以将其作为参数显式传递。如果您不知道要插入哪个实体,则可以传递每个实体继承的基类或接口。此类或接口将定义所有使用它的实体共有的属性,例如

      public class BaseEntity
      {
          public int Id {get; set;}
      }
      
      public partial class ModelName : BaseEntity
      { 
          //Properties unique to ModelName
      }
      

      您应该在模型之外编写映射代码。如果您想让控制器保持纤薄,您可以创建一个单独的中间层来执行此操作。

      考虑创建一个单独的类来容纳您的实体操作,而不是使用静态函数。我觉得在这里使用静态方法违反了 OO 设计。创建这个单独的类不需要您编写比现有更多的代码,但它会重新排列您的代码以使其看起来更清晰。

      public class BusinessService()
      {
          public int Insert(ModelName model)
          {
              ctx.TheTargetedEntity.Add(model);
              ctx.SaveChanges();
              return model.id;
          }
      }
      
      public class PresentationService()
      {
          public int Insert(MyActionViewModel theVm)
          {
              ModelName mn = new ModelName();
              mn.AddressLineOne = theVm.AddressLineOne;
              mn.AddressLineTwo = theVm.AddressLineTwo;
              return businessService.Insert(mn);
          }
      }
      

      我将添加项目引用如下: 控制器 -> PresentationService -> BusinessService -> DB

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 2012-10-18
        • 1970-01-01
        • 1970-01-01
        • 2019-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多