【问题标题】:How to use repository pattern in ASP.NET Core MVC while IdentityDbContext has been used?在使用 IdentityDbContext 的情况下,如何在 ASP.NET Core MVC 中使用存储库模式?
【发布时间】:2022-01-10 00:32:29
【问题描述】:

我在我的项目中使用了 IdentityDbContext。我的数据库有一些相互连接的表(关系)。我想使用存储库模式。我声明了我所有的接口。然后,我尝试实现它们。问题是我无法创建 IdentityAppContext 的实例,因为构造函数需要一个输入参数“选项”。 我该如何实现它们?

IdentityAppContext.cs:

public class IdentityAppContext: IdentityDbContext<AppUser, AppRole, int>
{
    public IdentityAppContext(DbContextOptions<IdentityAppContext> options) : base(options)
    {

    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
    public DbSet<AppUser> Users { get; set; }
    public DbSet<Message> Messages { get; set; }
    public DbSet<PM> PMs { get; set; }
    public DbSet<Notification> Notifications { get; set; }
    public DbSet<FileRepository> Files { get; set; }
}

IPmRepository.cs:

public interface IPmRepository
{
    IEnumerable<PM> GetAllPMs();
    PM GetPmById(int pmId);
    bool InsertPM(PM pm);
    bool UpdatePM(PM pm);
    bool DeletePM(int pmId);
    bool DeletePM(PM pm);
    void Save();
}

PmRepository.cs:

public class PmRepository : IPmRepository
{
    IdentityAppContext db = new IdentityAppContext();
    public IEnumerable<PM> GetAllPMs()
    {
        
    }
    public PM GetPmById(int pmId)
    {
        throw new NotImplementedException();
    }
    public bool InsertPM(PM pm)
    {
        throw new NotImplementedException();
    }
    public bool UpdatePM(PM pm)
    {
        throw new NotImplementedException();
    }
    public bool DeletePM(int pmId)
    {
        throw new NotImplementedException();
    }

    public bool DeletePM(PM pm)
    {
        throw new NotImplementedException();
    }
    public void Save()
    {
        throw new NotImplementedException();
    }
}

【问题讨论】:

  • 为什么你认为你需要使用存储库模式? DbSet 已经是一个单实体存储库。 DbContext 已经是一个多实体的工作单元。 GetAllPMs 方法很少有用 - 很少有任何理由加载表中的所有行,除非您想填充查找表。在像 ORM 这样的高级抽象上使用低级“存储库”接口实际上是一种模式
  • 与@PanagiotisKanavos 一致,避免使用反模式。这将帮助您在处理 IdentityDbContext 时进行设置:stackoverflow.com/questions/50377705/…,可能重复:stackoverflow.com/questions/23226140/…
  • 如果您想使用 DDD,请注意 DDD 使用存储库作为 聚合根 - 这是您需要加载以处理特定用途的对象图的根案例(DDD 术语中的有界上下文)。 单个实体。在这种情况下,是的,specialized Repository 是有意义的。在那个级别,绝对不需要具有 CRUD 方法的类,不需要加载表中的所有对象。
  • 至于IdentityDbContext为什么不能和new一起使用,那是因为它是用来和依赖注入一起使用的。使用该 DbContext 的类需要以相同的方式工作 - 而不是尝试手动创建它们的依赖项,而是接受它们作为构造函数参数。只需更改AddDbContext 中注册的选项或传递给构造函数的选项,就可以轻松地将底层存储从 SQL Server 更改为 MySQL 再到 Oracle 到 NoSQL 数据库。这样可以轻松进行单元测试 - 您可以使用内存提供程序,而无需修改 DbContext 或任何使用它的代码
  • 假设你真的定义了一个PmRepository,它需要一个接受IdentityAppContext参数的构造函数。

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


【解决方案1】:

假设 DbContext 已在 Startup.cs 文件中注册到 DI 容器,使用类似:

services.AddDbContext<IdentityAppContext>(opt => 
{
   opts.UseSqlServer(myConnectionString);
})

然后以与上述相同的方法添加以下内容,会将您的存储库注册到同一个 DI Container 中:

services.AddScoped<IPmRepository, PmRepository>();

然后在您的存储库中:

public class PmRepository : IPmRepository
{
    readonly IdentityAppContext _context;
 
    // 'context' parameter is automagically provided by the container.
    public PmRepository(IdentityAppContect context)
    {
        _context = context;
    }

    public bool InsertPM(PM pm)
    {
        _context.PMs.Add(pm);
    }
}

然后,在您的控制器(也由容器提供)中,您应该能够在构造函数中从容器请求 IPmRepository:

public class MyController : Controller
{
    readonly IdentityAppContext _context;
    readonly IPmRepository _pmRepository;

    // Both 'context' and 'pmRepository' are automagically provided by the container
    public MyController(
        IdentityAppContext context,
        IPmRepository pmRepository)
    {
        _context = context;
        _pmRepository = pmRepository;
    }

    [HttpPost]
    public async Task DoSomething(MyRequest request)
    {
        _pmRepository.InsertPM(new PM() { Id = request.Id });

        await _context.SaveChangesAsync();
    }
}

注意,由于IdentityAppContext和IPmRepository和MyController注册在同一个容器中,所以框架可以自动为MyController构造函数提供参数。

此外,当为 Controller 创建 PmRepository 时,容器可以查看 PmRepository 的构造函数参数,并看到它需要一个 IdentityAppContext,它可以自动提供,因为它注册在同一个容器中。

【讨论】:

    猜你喜欢
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2020-01-08
    • 2013-03-31
    • 1970-01-01
    相关资源
    最近更新 更多