如何在 ASP.NET MVC 中组织 DAL

How to organize DAL in ASP.NET MVC

我正在尝试在 asp.net mvc 项目中组织数据访问层。我已经阅读了很多关于这个的不同文章,所以我仍然有一些问题来解决这个问题:

  1. 我应该为数据库中的每个实体还是为所有或一个通用实例创建存储库实例,例如 PostRepository 可以包括像 Post、[=13= 这样的实体] 和 Tag?

  2. 在控制器中,我必须获取一些数据,将其转换为 ViewModel 并将其传递到视图中。最好的地方在哪里? ServicesController 还是其他?

  3. 如果是Service。我应该创建多少个服务?如果有必要,还为每个实体传递到 Controller 3 或 4 服务吗?或者也许像我想在存储库中那样做? (创建一个包含一些存储库的公共服务。PostService,存储库如 PostRepositoryCommentRepositoryTagRepository

这是我的看法:

Should I create instances of repository for every entity in database or for all or one genereal instance, for example PostRepository can include entities like Post, Comment and Tag?

拥有一个单一的通用存储库将为您省去很多令人头疼的维护工作。您可以实现单个通用存储库,例如:

/// <summary>
/// This interface provides an abstraction for accessing a data source.
/// </summary>
public interface IDataContext : IDisposable
{
    IQueryable<T> Query<T>() where T : class;

    T Add<T>(T item) where T : class;

    int Update<T>(T item) where T : class;

    void Delete<T>(T item) where T : class;

    /// <summary>
    /// Allow repositories to control when SaveChanges() is called
    /// </summary>
    int SaveChanges();
}

并在单个上下文中实现上述接口 class。

有些人也实现了单独的特定存储库。

In controller I have to get some data, transform in into ViewModel and pass it into view. Where is the best place to do this? Services, Controller or something else?

在可从 DA、服务和 Web 访问的单独程序集中定义所有模型(DTO 或实体或 POCO)classes。服务方法 returns 模型实例,控制器将它们转换为视图模型(使用 AutoMapper)并传递给视图。同样在post方法中,controller先将VM转成Model,再传给Service层进行持久化或处理。

If it is Service. How many services should I create? Also for every entity and pass into Controller 3 or 4 services if it is necessery? Or maybe do it like I wanted to do it in repository? (Create one common service which would contain some count of repositories. PostService, with repositories like PostRepository, CommentRepository and TagRepository)

我强烈建议您将服务定义得非常具体。使用单一职责原则来定义您的服务。每个服务都应该提供相关的功能集。例如。 AuthService 将对不向他们发送电子邮件的用户进行身份验证,即 EmailService 工作。

我建议的模式适用于不同的服务。例如:

public class DriverSearchService : IDriverSearchService
{
    private readonly IBlobService _blobService;
    private readonly IDataContext _dataContext;

    public DriverSearchService(IDataContext dataContext, IBlobService blobService)
     {
         _blobService = blobService;
        _dataContext = dataContext;
     }

    public void SaveDriveSearch(int searchId)
    {
        // Fetch values from temp store and clear temp store
        var item = context.Query<SearchTempStore>().Single(s => s.SearchId == searchId);

        // Temp object is latest so update the main store
        var mainSearch = context.Query<Search>().Single(s => s.Id == searchId);
        mainSearch.LastExecutedOn = DateTime.UtcNow;
        mainSearch.DataAsBlob = item.DataAsBlob;
        context.Update(mainSearch);
    }
}

基本上我同意@ChrFin 对你的评论 post 但我还是想回答你的问题。

  1. 可以,但前提是您需要。您应该考虑 Post 实体可能具有引用其他实体的虚拟属性。在这种情况下,您可能不需要单独的存储库。但是,您应该在加载相关实体时考虑性能问题

  2. 根据我的经验,映射到 ViewModel 的最佳位置是服务层或管理层 - 取决于您希望如何调用它。我总是尽量让我的控制器变薄。随着应用程序的增长,您可能希望在其他应用程序中重用您的逻辑,例如WCF。如果您的控制器中有转换、业务逻辑和其他内容,您将无法共享它们。

  3. 视情况而定。如果你想避免控制器中的多个依赖项(这也会对单元测试产生影响),你应该为每个控制器只创建一个服务——正如我所说,这不是规则。服务可能包含多个存储库。通常,您不需要存储库那么多的服务。

如果您开始开发应用程序,您应该在决定使用存储库模式之前检查这个有用的链接:

Favor query objects over repositories

Say No to the Repository Pattern in your DAL