【问题标题】:ASP.NET MVC Design Question - Where to put DB access code?ASP.NET MVC 设计问题 - 将数据库访问代码放在哪里?
【发布时间】:2011-01-23 15:43:11
【问题描述】:

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

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

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

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

谢谢。

    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();

【问题讨论】:

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


    【解决方案1】:

    您的数据库访问代码应该在存储库中。示例:

    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. 视图被强类型化到视图模型并使用它来编辑/显示

    就此存储库的实现而言,您可以随意使用您喜欢的任何数据访问技术(EF、NHibernate、Linq to XML、WCF 通过 Internet 调用远程资源,...)

    有以下优点:

    1. 控制器逻辑与数据访问逻辑完全解耦
    2. 您的控制器可以单独进行单元测试
    3. 您的模型中不包含应属于 UI 层的属性(例如 SelectListItem),因此可以在 ASP.NET MVC 以外的其他类型的应用程序中重用。
    4. 视图模型是一个专门针对视图需求量身定制的类,这意味着它将包含特定的格式化属性,并且视图代码的可读性极强。
    5. 您的视图是强类型 => 不再有 ViewData 和丑陋的魔术字符串

    【讨论】:

    • 很好,感谢您的回复。这是有道理的,我会试一试。
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

      查看存储库模式

      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/

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-12
        • 2015-07-11
        • 2010-12-15
        • 1970-01-01
        • 1970-01-01
        • 2016-08-13
        相关资源
        最近更新 更多