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

发布于 2024-10-14 07:01:05 字数 878 浏览 9 评论 0原文

过去几周我一直在研究 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();

I've been playing around with ASP.NET MVC for the past few weeks. I've got a simple web application with a form which contains a number of drop down lists.

The items in the drop down lists are stored in a database, and I'm using LINQ to SQL to retrieve them.

My question is - where's the appropriate place to put this code? From what I've read so far, it seems that it's advisible to keep the Controller 'thin', but that's where I currently have this code as it needs to be executed when the page loads.

Where should I be putting DB access code etc.? I've included an excerpt from my controller below.

Thanks.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤寂小茶 2024-10-21 07:01:05

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

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 和丑陋的魔法字符串

Your database access code should be in a repository. Example:

public interface ITranslationRepository
{
    Translation GetTransaltion();
}

and the controller would use this repository:

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

So the basic idea is the following:

  1. The controller queries a repository to fetch a model
  2. The controller maps this model to a view model (AutoMapper is great for this job)
  3. The controller passes the view model to the view
  4. The view is strongly typed to the view model and uses it to edit/display

As far as the implementation of this repository is concerned feel free to use any data access technology you like (EF, NHibernate, Linq to XML, WCF calls to remote resources over the internet, ...)

There are the following advantages:

  1. The controller logic is completely decoupled from the data access logic
  2. Your controllers can be unit tested in isolation
  3. Your models are not littered with properties that should belong to the UI layer (such as SelectListItem) and thus are reusable across other types of application than ASP.NET MVC.
  4. The view model is a class which is specifically tailored to the needs of the view meaning that it will contain specific formatted properties and the view code will be extremely readable.
  5. Your views are strongly typed => no more ViewData and ugly magic strings
顾北清歌寒 2024-10-21 07:01:05

建议您的数据访问代码应包含在其自己的项目/程序集中。它由 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
}

Suggest that your data-access code should be contained in its own project/assembly. That is referenced by the UI tier (ASP.NET MVC application). That'll help achieve the goal of keeping your Controllers thin, and keep all the data access code out of your MVC UI project.

That typically leads to another question/discussion about domain entities: when mapping to the data store. Some architects like to have the entities in their own separate assembly. This encourages reuse in other applications. Some like to keep the entity model and data access code in the same project/assembly. This is totally up to you and your environment.

For an example, let's say it's a billing application; holding customers, invoices, etc.
Your implementation will be different, depending on your data access strategy (an ORM like LINQ To SQL, EF, nHibernate, SubSonic, or plain old ADO.NET, or reading from a flat file).

// 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
}
断念 2024-10-21 07:01:05

查看存储库模式

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

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

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

Check out the Repository pattern

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/

The idea is you abstract your data access in something called a repository that returns domain objects. Your controller can then use this repository to get the appropriate objects from the database and assign them to the model.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文