ApplicationDbContext объявляет конструктор без параметров

#c# #asp.net #entity-framework

Вопрос:

Пытаясь изучить ядро EF, я только что закончил онлайн-курс, и я пытаюсь добавить целое число в таблицу БД. .Net 5.0.

Я получаю ошибку при сборке приложения:

«AddDbContext» был вызван с помощью конфигурации, но тип контекста «ApplicationDbContext» объявляет только конструктор без параметров. Это означает, что конфигурация, переданная в «AddDbContext», никогда не будет использоваться. Если конфигурация передается в «AddDbContext», то «ApplicationDbContext» должен объявить конструктор, который принимает DbContextOptions и должен передать его базовому конструктору для DbContext. Майкрософт.Расширения.Зависимость от инъекции.Расширения entityframeworkservicecollection.Проверьте конструкторы текста()

Я понимаю, что проблема между ApplicationDbContext.cs и Startup.cs, у одного есть параметры, а у другого нет параметров, но я не знаю, как это исправить. Другие ответы в Интернете, похоже, похожи на «Это очевидно, просто исправьте это», что не очень полезно.

ApplicationDbContext

Если я отменю комментарий к пустым ApplicationDbContext функциям, я больше не получу ошибку, но при запуске программы в мою базу данных ничего не добавляется.

 using System;
using System.Collections.Generic;
using System.Text;
using MyApp.Areas.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace MyApp.Data
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public DbSet<RGWAction> RGWActions { get; set; }

        DBConnectionStringFactory GetDBConnectionString = new DBConnectionStringFactory();
        
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string ConnectionString = GetDBConnectionString.DBConnectionString();

            optionsBuilder.UseSqlServer(ConnectionString).LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name },LogLevel.Information)
                .EnableSensitiveDataLogging(); //add to be able to see parameters in your log
        }
        /*
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {

        }

        public ApplicationDbContext()
        {

        }
        */
    }
}
 

Startup.cs

public void ConfigureServices(IServiceCollection services) метод

     services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
 

RGWAction.cs

 using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp.Areas.Identity
{
    public class RGWAction
    {
        public int Id { get; set; }
        public string Email { get; set; }
        public int Total { get; set; }
        public int ReduceMeat { get; set; }
    }
}
 

Программа.cs

Просто пытаюсь добавить целое число в базу данных при запуске прямо сейчас, чтобы заставить ее работать в качестве учебного упражнения. Моим следующим шагом будет вызвать его с помощью кнопки пользовательского интерфейса.

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MyApp.Data;
using MyApp.Areas.Identity;

namespace MyApp
{
    public class Program
    {
        private static ApplicationDbContext _context = new ApplicationDbContext();

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

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

        private static void InsertNewInteger()
        {
            _context.RGWActions.Add(new RGWAction { ReduceMeat = 1 });
            _context.SaveChanges();
        }
    }
}
 

Таблица БД:
введите описание изображения здесь

Совет был бы очень признателен.

Ответ №1:

Вам нужен конструктор ApplicationDbContext с параметром DbContextOptions для вставки зависимостей параметров.

Вам нужен конструктор по умолчанию без параметров, потому что вы вызываете его явно в инициализаторе поля _context. Попробуйте опустить эту инициализацию, она не нужна, если DI работает хорошо.

Ответ №2:

Ваш контроллер:

 public class YourController : Controller
{
    [HttpPost] // because data is updated
    public async Task<ActionResult> NewIntAction(
        [FromServices]
        INewIntService newIntService)
    {
            await newIntService.InsertNewInteger();
            ....
            return View(); // You will need a view NewIntAction in the folder Views/Your
    }
}
 

Интерфейс INewIntService :

 public interface INewIntService
{
    Task InsertNewInteger();
}
 

Новый класс обслуживания:

 public sealed class NewIntService : INewIntService
{
    public NewIntService(ApplicationDbContext context)
    {
        _context = context;
    }
    ApplicationDbContext _context;

    public async Task InsertNewInteger()
    {
        _context.RGWActions.Add(new RGWAction { ReduceMeat = 1 });
        await _context.SaveChangesAsync();
    }
}
 

Startup.cs:

     services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddTransient<INewIntService, NewIntService>();
 

Основная программа:

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

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

Мне не нужно определять конструктор ApplicationDbContext, потому что экземпляр ApplicationDbContext создается инфраструктурой и вводится в качестве зависимости в конструктор NewIntService в его параметре контекста.

Ответ №3:

Ааааа, наконец-то! 🙂

ApplicationDbContext нуждается во всех трех методах. Кто-нибудь знает, почему?

 OnConfiguring(DbContextOptionsBuilder optionsBuilder)
ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
ApplicationDbContext()
 

Кроме того, Program.cs был неподходящим местом для моего InsertNewInteger() метода. Это должно было быть в контроллере для загрузки страницы, в данном случае index.cs в контроллере.