ASP.NET MVC设计问题 - 在哪里放置DB访问代码?

时间:2011-01-23 15:43:12

标签: asp.net asp.net-mvc-2 code-organization

过去几周我一直在玩ASP.NET MVC。我有一个简单的Web应用程序,其表单包含许多下拉列表。

下拉列表中的项目存储在数据库中,我正在使用LINQ to SQL来检索它们。

我的问题是 - 放置此代码的适当位置在哪里?从我到目前为止所读到的内容来看,似乎建议保持Controller“瘦”,但这是我目前拥有此代码的地方,因为它需要在页面加载时执行。

我应该在哪里放置数据库访问代码等?我在下面列出了我的控制器摘录。

感谢。

    public ActionResult Index()
    {
        TranslationRequestModel trm = new TranslationRequestModel();

        // Get the list of supported languages from the DB
        var db = new TransDBDataContext();
        IEnumerable<SelectListItem> languages = db.trans_SupportedLanguages
            .Select(c => new SelectListItem
                {
                    Value = Convert.ToString(c.ID),
                    Text = c.Name.ToString()

                });
        ViewData["SourceLanguages"] = languages;
        ViewData["TargetLanguages"] = languages;
        return View();

3 个答案:

答案 0 :(得分:4)

您的数据库访问代码应位于存储库中。例如:

public interface ITranslationRepository
{
    Translation GetTransaltion();
}

并且控制器将使用此存储库:

public class TransaltionController : Controller
{
    private readonly ITranslationRepository _repository;
    public TransaltionController(ITranslationRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        // query the repository to fetch a model
        Translation translation = _repository.GetTransaltion();

        // use AutoMapper to map between the model and the view model
        TranslationViewModel viewModel = Mapper.Map<Translation, TranslationViewModel>(model);

        // pass the view model to the view
        return View(viewModel);
    }
}

所以基本思路如下:

  1. 控制器查询存储库以获取模型
  2. 控制器将此模型映射到视图模型(AutoMapper非常适合此作业)
  3. 控制器将视图模型传递给视图
  4. 视图强烈地键入视图模型并使用它来编辑/显示
  5. 关于此存储库的实现,请随意使用您喜欢的任何数据访问技术(EF,NHibernate,Linq to XML,WCF通过Internet调用远程资源,...)

    有以下优点:

    1. 控制器逻辑与数据访问逻辑
    2. 完全分离
    3. 您的控制器可以单独进行单元测试
    4. 您的模型不会充斥着属于UI层的属性(例如SelectListItem),因此可以在除ASP.NET MVC之外的其他类型的应用程序中重复使用。
    5. 视图模型是专门根据视图需求量身定制的类,这意味着它将包含特定的格式化属性,并且视图代码将具有极高的可读性。
    6. 您的观点是强类型=&gt;没有更多ViewData和丑陋的魔术字符串

答案 1 :(得分:1)

建议您的数据访问代码包含在自己的项目/程序集中。这是由UI层(ASP.NET MVC应用程序)引用的。这将有助于实现保持控制器精简的目标,并将所有数据访问代码保留在MVC UI项目之外。

这通常会引发关于域实体的另一个问题/讨论:映射到数据存储时。一些建筑师喜欢将实体放在他们自己的独立装配中。这鼓励在其他应用程序中重用。有些人喜欢将实体模型和数据访问代码保存在同一个项目/程序集中。这完全取决于您和您的环境。

举个例子,假设这是一个结算应用程序;持有客户,发票等 您的实现将有所不同,具体取决于您的数据访问策略(ORM,如LINQ To SQL,EF,nHibernate,SubSonic或普通的旧ADO.NET,或从平面文件读取)。

// Assembly: InvoicingDL
public class CustomerRepo
{
    public IQueryable<Customer> ListCustomers()
    {
        return MyDatabase.Customers(); //however you'd get all your customers
    }    
    //etc
}

// Assembly: InvoicingDL
public class InvoicingRepo
{
    public IQueryable<Invoice> GetCustomerInvoices(int custID)
    {
        return MyDatabase.Invoices.Where(i=>i.CustomerID==custID); 
    }    
    //etc
}

答案 2 :(得分:1)

查看存储库模式

https://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx

http://www.mindscapehq.com/blog/index.php/2008/05/12/using-the-unit-of-work-per-request-pattern-in-aspnet-mvc/

您的想法是在称为存储库的东西中抽象数据访问,该存储库返回域对象。然后,您的控制器可以使用此存储库从数据库中获取相应的对象,并将它们分配给模型。