#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
в контроллере.