【问题标题】:InvalidOperationException: No database provider has been configured for this DbContext with Repository patternInvalidOperationException:没有为此 DbContext 配置具有存储库模式的数据库提供程序
【发布时间】:2021-02-09 15:38:25
【问题描述】:

请问ASP.Net core 中的Entity framework core 有问题。 首先我是EF CoreASP.Net Core 的业余爱好者。

想法:

当我使用多个上下文时,我正在尝试创建一个通用存储库来执行一些重复的例程而不重复代码。

Repo 类:

public sealed class Repo<TContext> : IRepo<TContext>, IDisposable where TContext : DbContext, new()
{

    


    #region properties

    /// <summary>
    /// Private DBContext property
    /// </summary>
    private DbContext _Context { get; } = null;


    /// <summary>
    /// Determine if Lazy Loading either activate or not
    /// </summary>
    private bool _LazyLoaded { get; set; }

    #endregion




    #region Construcors


    public Repo(bool LazyLoaded)
    {
        _Context                                  = new TContext();
        _LazyLoaded                               = LazyLoaded;
        _Context.ChangeTracker.LazyLoadingEnabled = LazyLoaded;
    }


    #endregion



    
    #region Routines

    


    #region Select

        /// <summary>
        /// Get All records from a table
        /// </summary>
        /// <typeparam name="TEntity">The entity to select from</typeparam>
        /// <returns></returns>
        public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
        {
            return _Context.Set<TEntity>().ToList();
        }



        /// <summary>
        /// Asynchronously, Get All records from a table
        /// </summary>
        /// <typeparam name="TEntity">The entity to select from</typeparam>
        /// <returns></returns>
        public Task<IEnumerable<TEntity>> GetAllAsync<TEntity>() where TEntity : class
        {
            return Task.Factory.StartNew(() => GetAll<TEntity>());
        }




        /// <summary>
        /// Get One record from a table, based on the primary key value
        /// </summary>
        /// <typeparam name="TEntity">The entity to select from</typeparam>
        /// <param name="pkValue">The primary key value</param>
        /// <returns></returns>
        public TEntity GetOne<TEntity>(object pkValue) where TEntity : class
        {
            return _Context.Set<TEntity>().Find(pkValue);
        }



        /// <summary>
        /// Asynchronously, Get One record from a table, based on the primary key value
        /// </summary>
        /// <typeparam name="TEntity">The entity to select from</typeparam>
        /// <param name="pkValue">The primary key value</param>
        /// <returns></returns>
        public Task<TEntity> GetOneAsync<TEntity>(object pkValue) where TEntity : class
        {
            return Task.Factory.StartNew(() => GetOne<TEntity>(pkValue));
        }






        #region Preview feature


         /// <summary>
        /// Get Many records from a table based on a property value
        /// </summary>
        /// <typeparam name="TEntity">The entity to select from</typeparam>
        /// <param name="prop">The property used in the condition</param>
        /// <param name="val">The value that will used in the search</param>
        /// <returns></returns>
        public IEnumerable<TEntity> GetMany<TEntity>(string prop, object val) where TEntity : class
        {
            return _Context.Set<TEntity>().AsEnumerable()
                           .Where(x => typeof(TEntity).GetProperty(prop).GetValue(x, null).ToString()
                                                      .Contains(val.ToString())).ToList();
        }

    #endregion




    #endregion



    #region Contains

    /// <summary>
    /// Check if a entity contains an object
    /// </summary>
    /// <typeparam name="TEntity">Entity to be look in</typeparam>
    /// <param name="obj">The object to be looking for</param>
    /// <returns></returns>
    public bool Contains<TEntity>(TEntity obj) where TEntity : class
    {
        return _Context.Set<TEntity>().AsEnumerable().Contains(obj);
    }


    /// <summary>
    /// Asynchronously Check if a entity contains an object
    /// </summary>
    /// <typeparam name="TEntity">Entity to be look in</typeparam>
    /// <param name="obj">The object to be looking for</param>
    /// <returns></returns>
    public Task<bool> ContainsAsync<TEntity>(TEntity obj) where TEntity : class
    {
        return Task.Factory.StartNew(() => Contains<TEntity>(obj));
    }




    /// <summary>
    ///  Check if a entity contains an object based on a custom EQUALITY Comparer
    /// </summary>
    /// <typeparam name="TEntity">Entity to be look in</typeparam>
    /// <typeparam name="TEntityComparer">The custom TEntity EQUALITY Comparer</typeparam>
    /// <param name="obj">The object to be looking for</param>
    /// <returns></returns>
    public bool Contains<TEntity, TEntityComparer>(TEntity obj)
        where TEntity : class
        where TEntityComparer : IEqualityComparer<TEntity>, new()
    {
        return _Context.Set<TEntity>().AsEnumerable().Contains(obj,new TEntityComparer() as IEqualityComparer<TEntity>);
    }



    /// <summary>
    ///  Asynchronously Check if a entity contains an object based on a custom EQUALITY Comparer
    /// </summary>
    /// <typeparam name="TEntity">Entity to be look in</typeparam>
    /// <typeparam name="TEntityComparer">The custom TEntity EQUALITY Comparer</typeparam>
    /// <param name="obj">The object to be looking for</param>
    /// <returns></returns>
    public Task<bool> ContainsAsync<TEntity, TEntityComparer>(TEntity obj)
        where TEntity : class
        where TEntityComparer : IEqualityComparer<TEntity>, new()
    {
        return Task.Factory.StartNew(() => Contains<TEntity, TEntityComparer>(obj));
    }

    #endregion



    #region Insert



    /// <summary>
    /// Insert one record into the database table
    /// </summary>
    /// <typeparam name="TEntity">Entity to add into</typeparam>
    /// <param name="record">The record to be added</param>
    public void Insert<TEntity>(TEntity record) where TEntity : class
        {
            _Context.Set<TEntity>().Add(record);
        }



        /// <summary>
        /// Asynchronously, Insert one record into the database table
        /// </summary>
        /// <typeparam name="TEntity">Entity to add into</typeparam>
        /// <param name="record">The record to be added</param>
        public Task InsertAsync<TEntity>(TEntity record) where TEntity : class
        {
            return Task.Factory.StartNew(() => Insert(record));
        }



        /// <summary>
        /// Insert a range of reords in a table
        /// </summary>
        /// <typeparam name="TEntity">Entity to insert into</typeparam>
        /// <param name="records">Records to be inserted</param>
        public void InsertRange<TEntity>(List<TEntity> records) where TEntity : class
        {
            _Context.Set<TEntity>().AddRange(records);
        }



        /// <summary>
        /// Asynchronously, Insert a range of reords in a table
        /// </summary>
        /// <typeparam name="TEntity">Entity to insert into</typeparam>
        /// <param name="records">Records to be inserted</param>
        public Task InsertRangeAsync<TEntity>(List<TEntity> records) where TEntity : class
        {
            return Task.Factory.StartNew(() => InsertRange(records));
        }



        #endregion




    #region Delete

        /// <summary>
        /// Delete One record from a database table
        /// </summary>
        /// <typeparam name="TEntity">Entity to remove from</typeparam>
        /// <param name="record">The record to be removed</param>
        public void Delete<TEntity>(TEntity record) where TEntity : class
        {
            this._Context.Set<TEntity>().Remove(record);
        }



        /// <summary>
        /// Asynchronously, Delete One record from a database table
        /// </summary>
        /// <typeparam name="TEntity">Entity to remove from</typeparam>
        /// <param name="record">The record to be removed</param>
        public Task DeleteAsync<TEntity>(TEntity record) where TEntity : class
        {
            return Task.Factory.StartNew(() => Delete(record));
        }


        #endregion




        /// <summary>
        /// Save the repository changes
        /// </summary>
        public void Save()
        {
            _Context.SaveChanges();
        }


    #endregion




    #region Disposing


        #region Properties

        private bool _disposed { get; set; } = false;

        #endregion


        private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _Context.Dispose();
                }
            }

            _disposed = true;
        }



        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }


    #endregion


}

在 ASP.Net 核心中:

Models

  public class Client
    {
        [Key]
        public string ID { get;                         set; }
        public         string             Name   { get; set; }
        public         int                Age    { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
    }


public class Order
{
    [Key]
    public int ID { get;        set; }
    public Client  CLT   { get; set; }
    public string  PRD   { get; set; }
    public decimal Total { get; set; }
}

代码优先 DbContext:

 public class TrainContext:DbContext
    {
        public TrainContext(DbContextOptions<TrainContext> contextOptions) : base(contextOptions)
        {

        }

        public TrainContext()
        {
            
        }

        protected void OnModelCreating(ModelBuilder builder)
        {
            foreach (var property in builder.Model.GetEntityTypes().SelectMany(t => t.GetProperties()).Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
            {
                property.SetColumnType("decimal(18,2)");
            }
        }

        #region DB Sets

        public virtual DbSet<Client> Client { get; set; }
        public virtual  DbSet<Order>  Order  { get; set; }

        #endregion
    }

Client 控制器:

 public class ClientController : Controller
    {
        private readonly Repo<TrainContext> db = new Repo<TrainContext>(false);

        private readonly TrainContext _context;

        public ClientController(TrainContext context)
        {
            _context = context;
        }
        public IActionResult Index()
        {



            //var data = _context.GetAll<Models.Client>();
            var data = _context.Client.ToList();

            ViewBag.Clients = data;

            return View();
        }
    }

Startup.cs ConfigureServices 方法:

  public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddDbContext<TrainContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DB")));

        }

AppSettings.Json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DB": "Server=ServerName; Database=GOrders;Integrated Security=True"
  }
}

问题:

问题是,当我在 控制台应用程序中传递 Db First Context 时,此存储库工作正常。

但是当我尝试在我的Asp.Net core 应用程序中使用Code first 方法时,我收到了这个错误:

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.

请帮忙解决这个问题?并提前非常感谢。

【问题讨论】:

  • 您的DbContext 未配置特定的数据库提供程序。您可以通过覆盖OnConfiguring 方法或在ConfigureServices 类中的ConfigureServices 方法中使用AddDbContext 来配置它。异常消息也清楚地说明了如何解决问题。我很确定,在搜索该错误时,您应该能够自己找到解决方案。
  • 请您在您的许可和非常感谢您的时间先生后提供一个解决方案作为答案
  • 嗨@XDev,我的回答是否帮助您解决了您的问题?如果可以,请您接受作为答案吗?如果没有,请您跟进让我知道吗?参考:How to accept as answer .谢谢。

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


【解决方案1】:

正如错误信息所说:

可以通过覆盖 'DbContext.OnConfiguring' 方法或通过在 应用服务提供商。

两种方法可以满足您的要求。

第一种方式,覆盖DbContext.OnConfiguring

public class TrainContext : DbContext
{
    public TrainContext(DbContextOptions<TrainContext> contextOptions) : base(contextOptions)
    {

    }

    public TrainContext()
    {

    }

    protected void OnModelCreating(ModelBuilder builder)
    {

        foreach (var property in builder.Model.GetEntityTypes().SelectMany(t => t.GetProperties()).Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
        {
            property.SetColumnType("decimal(18,2)");
        }
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb; Database=GOrders;Integrated Security=true");
    }

    #region DB Sets

    public virtual DbSet<Client> Client { get; set; }
    public virtual DbSet<Order> Order { get; set; }

    #endregion
}

第二种方式使用AddDbContext,但是在使用AddDbContext之前,你需要添加一些缺失的东西:

修改 Program.cs:

using Microsoft.AspNetCore.Hosting;  //be sure add these references
using Microsoft.Extensions.Hosting;

class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
          webBuilder.UseStartup<Startup>();
      });
}

然后将.csproj文件中的Sdk="Microsoft.NET.Sdk"修改为Sdk="Microsoft.NET.Sdk.Web"如下:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

</Project>

您可以查看以下参考的详细原因:

https://stackoverflow.com/a/58097655/11398810

Startup.cs(确保您在 Startup.cs 中有 Configure 方法):

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<TrainContext>(options => 
        options.UseSqlServer(Configuration.GetConnectionString("DB")));

    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

如上修改后,就可以运行add-migraiton initupdate-database命令了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 2019-02-17
    • 2016-11-15
    • 2021-05-04
    • 2018-11-12
    • 2018-12-15
    • 2020-06-16
    相关资源
    最近更新 更多