Почему EF7 говорит, что я не настроил каких-либо поставщиков, когда ASP.net Identity отлично работает с тем же DbContext?

asp.net-core c# ef-code-first entity-framework-core

Вопрос

Я только начал работу над экспериментальным проектом с использованием ASP.net 5, MVC6 и Entity Framework 7. У меня есть ASP.Net Identity, работающий нормально, но затем попытался добавить некоторые из моих собственных данных в DbContext и решить эту проблему. Отчеты EF7:

При обработке запроса возникло необработанное исключение.

InvalidOperationException: не настроены поставщики баз данных. Настройте поставщика базы данных путем переопределения OnConfiguring в вашем классе DbContext или в методе AddDbContext при настройке служб.

Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices (ServiceProviderSource providerSource) Стек Cookie Cookies Заголовки

InvalidOperationException: не настроены поставщики баз данных. Настройте поставщика базы данных путем переопределения OnConfiguring в вашем классе DbContext или в методе AddDbContext при настройке служб.

Вот мой способ настройки:

    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Add application services.
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();

        services.AddTransient<ApplicationUnitOfWork>(instance => new ApplicationUnitOfWork());
    }

ApplicationUnitOfWork - это фасад над EF7 для уменьшения жесткой связи. Вот и все:

public class ApplicationUnitOfWork : IUnitOfWork
    {
    readonly ApplicationDbContext dbContext;

    public ApplicationUnitOfWork()
        {
        dbContext = new ApplicationDbContext();
        Products = new ProductRepository(dbContext);
        }

    public void Dispose() { dbContext.Dispose(); }

    public IUserRepository Users { get; }

    public IRepository<SoftwareProduct> Products { get; }

    public async Task CommitAsync() { await dbContext.SaveChangesAsync(); }

    public void Cancel() { throw new NotImplementedException(); }
    }

Теперь, когда я запускаю веб-приложение, я могу зарегистрировать учетную запись пользователя и войти в систему, а EF создает базу данных, создает таблицы Identity и заполняет их пользовательскими данными. Таблица продуктов также создана - так ясно на некотором уровне EF может использовать ApplicationDbContext и найти поставщика, который он использует для создания базы данных и схемы.

Однако, когда я пытаюсь получить доступ к контроллеру продуктов, который использует ProductsRepository , EF жалуется - хотя ApplicationDbContext используется в обоих случаях и использовался для создания базы данных!

Так почему? Что особенного в ASP.net Identity, что он может каким-то образом получить провайдера, но мой собственный код не может? Какое «магическое заклинание» мне не хватает?

Принятый ответ

его, потому что вы новичок, вместо того, чтобы его вводили для вас. Тот, который вы новичок, не настроен. Вы должны изменить свой класс, чтобы передать его в конструктор.

DbContext имеет несколько конструкторов, и вы используете пустой, который не настраивает его.

Лучше позволить ему впрыснуть, создав свой конструктор следующим образом:

 public ApplicationUnitOfWork(ApplicationDbContext context)
 {
    dbContext = context;
    Products = new ProductRepository(dbContext);
 }

ваш код показывает, что ApplicationDbContext был зарегистрирован в DI, Identity использует введенный, но вы не с тех пор, как вы внедрили его самостоятельно без конструктора без параметров

вы также должны зарегистрировать свой ApplicationUnitOfWork, чтобы его можно было ввести:

services.AddScoped<ApplicationUnitOfWork, ApplicationUnitOfWork>();


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow