【问题标题】:C#: Inherit from DbContext in Net Core, Constructor: No database provider has been configured for this DbContextC#:从 Net Core 中的 DbContext 继承,构造函数:没有为此 DbContext 配置数据库提供程序
【发布时间】:2020-04-30 21:59:39
【问题描述】:

我目前有如下的 PropertyApplication DbContext,

public partial class PropertyContext : DbContext
{
    public PropertyContext()
    {
    }

    public PropertyContext(DbContextOptions<PropertyContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Address> Address { get; set; }
    public virtual DbSet<BoundaryChangeEvent> BoundaryChangeEvent { get; set; }

我想从这个 PropertyDbContext 继承。这在构造函数中是否正确完成?试图通过下面的单元测试,它会覆盖保存更改以引入审核用户信息。只是好奇下面的构造函数语句是否正确?或者我应该尝试使用 AuditablePropertyContext 选项尝试下面的选项 2?

public class AuditablePropertyContext : PropertyContext
{
    private int _user;

    public AuditablePropertyContext()
    {
    }

    public AuditablePropertyContext(DbContextOptions<PropertyContext> options, UserResolverService userService)
        : base(options)
    {
        _user = userService.GetUser();
    }

    public void ApplyCreatedBy()
    {
        var modifiedEntities = ChangeTracker.Entries<ICreatedByUserId>().Where(e => e.State == EntityState.Added);
        foreach (var entity in modifiedEntities)
        {
            entity.Property("CreatedByUserId").CurrentValue = _user;
        }
    }

    public override int SaveChanges()
    {
        ApplyCreatedBy();
        return base.SaveChanges();
    }

}

选项 2:

我在尝试执行此操作时收到错误,

public AuditablePropertyContext(DbContextOptions<AuditablePropertyContext> options, UserResolverService userService)
    : base(options)
{
    _user = userService.GetUser();
}

错误:

错误 CS1503 参数 1:无法从“Microsoft.EntityFrameworkCore.DbContextOptions IPTS.PropertyManagement.Infrastructure.Auditable.Data.AuditablePropertyContext”转换为“Microsoft.EntityFrameworkCore.DbContextOptions IPTS.PropertyManagement.Infrastructure.Data.PropertyContext”

*有时公司使用 SQL Server,有时使用 InMemory 或 SQLite

单元测试失败:

services.AddSingleton(a =>
{
    var mock = new Mock<IUserResolverService>();
    mock.Setup(b => b.GetUser()).Returns(5);
    return mock.Object;
});

services.AddDbContext<PropertyContext>(
    options => options.UseInMemoryDatabase("Ipts").UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll),
    ServiceLifetime.Singleton);
services.AddSingleton<DbContext, PropertyContext>();


services.AddDbContext<AuditablePropertyContext>(
    options => options.UseInMemoryDatabase("Ipts").UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll),
    ServiceLifetime.Singleton);
services.AddSingleton<AuditablePropertyContext>();

services.RegisterMappingProfiles(new ApplicationServicesMappingProfile(),
    new PropertyManagementDataMappingProfile());
return services;

}

单元测试:错误

Message: 
System.InvalidOperationException : No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
Stack Trace: 
DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
DbContext.get_InternalServiceProvider()
DbContext.get_DbContextDependencies()

【问题讨论】:

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


    【解决方案1】:

    将构造函数PropertyContext类改成如下代码:

    public PropertyContext(DbContextOptions options)
            : base(options)
        {
        }
    

    然后将构造函数AuditablePropertyContext类改成如下代码:

      public AuditablePropertyContext(DbContextOptions options, UserResolverService userService)
            : base(options)
        {
            _user = userService.GetUser();
        }
    

    注意:当你不需要时,删除两个类中的默认构造函数。

    【讨论】:

    • 不知道团队为什么要这样,但我认为他们想保持这样?也许在此之上创建了另一个构造函数?无论如何,我的单元测试仍然失败,谢谢- public PropertyContext(DbContextOptions options) : base(options) {
    • @AlanSmith5482 这是一个合乎逻辑的变化,而且很常见。
    • 您好!快速提问,如果我把它作为一个构造函数,同时在你提供的新元素上添加,会有什么后果?我想保持我的老队友代码不变,public AuditablePropertyContext(DbContextOptions options, UserResolverService userService) : base(options) { _user = userService.GetUser(); }
    • 也欢迎提出问题
    【解决方案2】:

    您还可以仅在具体子类型上提供专门的DbContextOptions&lt;Repo&gt;

    例如

    public abstract class BaseRepo: DbContext
    {
        public BaseRepo(DbContextOptions options) : base(options)
        {
    
        }
    }
    
    
    public sealed class Repo : BaseRepo
    {
        public Repo(DbContextOptions<Repo> options) : base(options)
        {
    
        }
    }
    

    【讨论】:

    • 您好!快速提问,如果我将它作为构造函数保留,同时添加您提供的新构造函数,会有什么后果?我想保持我的队友代码完整,public AuditablePropertyContext(DbContextOptions options, UserResolverService userService) : base(options) { _user = userService.GetUser(); }
    猜你喜欢
    • 2017-09-02
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    相关资源
    最近更新 更多