如何在ASP.NET Core MVC中设计具有依赖注入的存储库模式?

时间:2017-02-21 00:08:42

标签: c# asp.net-mvc asp.net-core-mvc repository-pattern

作为ASP.NET Core 1.0 MVC的新手,我决定将一个存储库模式用于MVC Core应用程序;我使用SQL DB作为数据层SampleDbContext,我希望为我的一些业务实体提供一个Repository类。到目前为止,我已在startup.csCustomerController.csCustomerRepository.cs文件中完成了以下操作,其中示例实体为"客户"。

在Startup Class的ConfigureServices方法中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SampleDbContext>(options =>
       options.UseSqlServer(Configuration.GetConnectionString("SampleDB")));
}

在控制器中:

public class CustomerController : Controller
{

    private SampleDBContext _context;
    private CustomerRepository = new CustomerRepository (new SampleDBContext());

    public CustomerController(SampleDBContext context)
    {
        _context = context;
    }
}

在存储库中:

public class CustomerRepository
{
    private SampleDBContext _context;

    public CustomerRepository(SampleDBContext context)
    {
        _context = context;
    }
}

通过这种设计,我将SampleDbContext作为服务插入startup.cs一次,然后对于每个Controller(接收依赖注入)我实例化一个相应的存储库,传递新的实例SampleDbContext。 这种重复的DB上下文实例是多用户环境的良好设计吗? 我想我可以将每个存储库作为服务添加到startup.cs,但这看起来并不好看。 请告诉我一个好的设计实现,或者如果我迷路了,请把我放在正确的轨道上。

3 个答案:

答案 0 :(得分:27)

您可以看到simple example如何使用存储库模式:

您创建存储库界面:

using System.Collections.Generic;

namespace TodoApi.Models
{
    public interface ITodoRepository
    {
        void Add(TodoItem item);
        IEnumerable<TodoItem> GetAll();
        TodoItem Find(long key);
        void Remove(long key);
        void Update(TodoItem item);
    }
}

然后实施它:

using System;
using System.Collections.Generic;
using System.Linq;

namespace TodoApi.Models
{
    public class TodoRepository : ITodoRepository
    {
        private readonly TodoContext _context;

        public TodoRepository(TodoContext context)
        {
            _context = context;
            Add(new TodoItem { Name = "Item1" });
        }

        public IEnumerable<TodoItem> GetAll()
        {
            return _context.TodoItems.ToList();
        }

        public void Add(TodoItem item)
        {
            _context.TodoItems.Add(item);
            _context.SaveChanges();
        }

        public TodoItem Find(long key)
        {
            return _context.TodoItems.FirstOrDefault(t => t.Key == key);
        }

        public void Remove(long key)
        {
            var entity = _context.TodoItems.First(t => t.Key == key);
            _context.TodoItems.Remove(entity);
            _context.SaveChanges();
        }

        public void Update(TodoItem item)
        {
            _context.TodoItems.Update(item);
            _context.SaveChanges();
        }
    }
}

然后在ConfigureServices中注册:

services.AddSingleton<ITodoRepository, TodoRepository>();

然后将其注入Controller:

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    public class TodoController : Controller
    {
        public TodoController(ITodoRepository todoItems)
        {
            TodoItems = todoItems;
        }
        public ITodoRepository TodoItems { get; set; }
    }
}

答案 1 :(得分:2)

有些人认为DbContext本身就是一个存储库模式。如果您想要走这条路线,可以在ASP.NET Core and Angular 2下载示例代码。

例如 -

var monitor = setInterval(function() {
    var elem = document.activeElement;
    if(elem && elem.tagName == 'IFRAME'){
        if (elem.closest('.class_one') !== null) {
            alert('this iframe has a parent with class class_one');
        }
        else if (elem.closest('.class_two') !== null) {
            alert('this iframe has a parent with class class_two');
        }   
        else if (elem.closest('.class_three') !== null) {
            alert('this iframe has a parent with class class_three');
        }     
        clearInterval(monitor);
    }
}, 500);

Startup.cs

public class CustomerController : Controller
{
    private SampleDBContext _context;

    public CustomerController(SampleDBContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index(int id)
    {
        var user = _context.Users.Where(i => i.Id == id).FirstOrDefault();
        ...
    }
}

答案 2 :(得分:1)

我不确定它是最好的方法,但我总是将存储库创建为控制器实现的接口。

IRepository.cs:

public interface IRepository
{
     SomeList GetSomeList(string userId);
     Some GetSomeDetail(int someId);
}

DbInterface.cs:

public class DbInterface : IRepository
{
    public SomeList GetSomeList(string userId)
    {

    }

    public Some GetSomeDetail(int someId)
    {

    }
}

SomeList是我定义的数据类型,其中所有属性都作为列表显示在页面上。即任务应用程序中的任务列表。有些是定义的数据类型,它返回 a 任务的详细信息(因此输入将是taskId等)。

如果这是一个糟糕的方法,很高兴得到纠正。