Blazor Server (EF Core) и подключение к базе данных

avatar
BTOM
9 августа 2021 в 06:55
225
0
0

Извините за элементарный вопрос.

В настоящее время я изучаю разработку приложений с помощью Blazor Server, и у меня возникают проблемы с подключением к базе данных.

Я пытаюсь использовать DI для подключения к базе данных. Я создал код, использующий заводской шаблон, как показано ниже, но возникает ошибка в части, которая получает строку подключения.

    public void ConfigureServices(IServiceCollection services)
    {
        //error:CS0121  Inappropriate call between the following methods or properties: 'Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContextFactory<TContext>(Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Action<Microsoft.EntityFrameworkCore.DbContextOptionsBuilder>  Microsoft.Extensions.DependencyInjection.ServiceLifetime)' と 'BlazorSv.Models.FactoryExtensions.AddDbContextFactory<TContext>(Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Action<Microsoft.EntityFrameworkCore.DbContextOptionsBuilder>  Microsoft.Extensions.DependencyInjection.ServiceLifetime)'

        services.AddDbContextFactory<BlazorSv.Models.SQLbeginnerContext>(options => options.UseNpgsql(Configuration.GetConnectionString("DBConnection")));
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
    }

Я думал, что определение части <Models.SQLbeginnerContext> неоднозначно, поэтому я написал иерархию, но это не сработало.

Что делать с этой ошибкой? Мне нужен совет

Ниже приведен файл SQLbegginerContext.cs, в котором описывается файл StartUp.cs и шаблон фабрики.

StartUp.cs

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        //error:CS0121  Inappropriate call between the following methods or properties: 'Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContextFactory<TContext>(Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Action<Microsoft.EntityFrameworkCore.DbContextOptionsBuilder>  Microsoft.Extensions.DependencyInjection.ServiceLifetime)' と 'BlazorSv.Models.FactoryExtensions.AddDbContextFactory<TContext>(Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Action<Microsoft.EntityFrameworkCore.DbContextOptionsBuilder>  Microsoft.Extensions.DependencyInjection.ServiceLifetime)'

        services.AddDbContextFactory<Models.SQLbeginnerContext>(options => options.UseNpgsql(Configuration.GetConnectionString("DBConnection")));
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/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.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        });
    }
}

SQLbegginerContext.cs

public interface IDbContextFactory<TContext> where TContext : DbContext
{
    TContext CreateDbContext();
}

public class blazordbFactory<TContext> : IDbContextFactory<TContext> where TContext : DbContext
{
    public blazordbFactory(IServiceProvider provider)
    {
        this.provider = provider;
    }
    private readonly IServiceProvider provider;
    public TContext CreateDbContext()
    {
        return ActivatorUtilities.CreateInstance<TContext>(provider);
    }
}

public static class FactoryExtensions
{
    public static IServiceCollection AddDbContextFactory<TContext>(
        this IServiceCollection collection,
        Action<DbContextOptionsBuilder> optionsAction = null,
        ServiceLifetime contextAndOptionsLifetime = ServiceLifetime.Singleton)
        where TContext : DbContext
    {
        collection.Add(new ServiceDescriptor(
            typeof(IDbContextFactory<TContext>),
            sp => new blazordbFactory<TContext>(sp),
            contextAndOptionsLifetime));
        collection.Add(new ServiceDescriptor(
            typeof(DbContextOptions<TContext>),
            sp => GetOptions<TContext>(optionsAction, sp),
            contextAndOptionsLifetime));

        return collection;
    }
    private static DbContextOptions<TContext> GetOptions<TContext>(
        Action<DbContextOptionsBuilder> action,
        IServiceProvider sp = null) where TContext : DbContext
    {
        var optionsBuilder = new DbContextOptionsBuilder<TContext>();
        if (sp != null)
        {
            optionsBuilder.UseApplicationServiceProvider(sp);
        }
        action?.Invoke(optionsBuilder);
        return optionsBuilder.Options;
    }
}


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

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

Комментарий:SQLbegginer.cs

//Comment out this part
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){
 if (!optionsBuilder.IsConfigured)
    {
      optionsBuilder.UseNpgsql("Host=localhost; Database=SQLbeginner; Username=user; Password=****")
    }
}
Источник
Ivan Stoev
9 августа 2021 в 07:20
0

Почему эти пользовательские IDbContextFactory<TContext>, blazordbFactory<TContext> и FactoryExtensions? Потому что EF Core предоставляет такие готовые решения, а они конфликтуют с EF Core.

BTOM
9 августа 2021 в 07:40
0

благодарю вас. Этот код является копией примера кода на github. Означает ли это, что EF Core не подходит? Извините, мой английский не очень хорош. Кроме того, мне жаль, что я не ответил на вопрос должным образом.

Ivan Stoev
9 августа 2021 в 07:49
0

Я имею в виду, что в EF Core есть все эти методы. Я не знаю, какой образец кода github вы используете, и почему эти 3 пользовательские вещи были добавлены туда, поэтому я бы прокомментировал их и оставил только класс SQLbeginnerContext.

BTOM
9 августа 2021 в 08:19
0

простите. Я не знал, смогу ли я опубликовать его, потому что это был чужой код. Я добавил код в столбец вопросов. В SQLbegginer.cs есть метод OnConfiguring, и я закомментировал эту часть и написал код, включающий IDbContextFactory <TContext> blazordbFactory <TContext> и FactoryExtensions. Вы имеете в виду эту часть конфликта?

BTOM
9 августа 2021 в 11:01
1

Возможно, вы поняли, почему это не сработало. Метод, который я писал, был до .Net Core3, а моя среда была .Net5. Как было рекомендовано, services.AddDbContextFactory <Models.SQLbeginnerContext> (options => options.UseNpgsql (Configuration.GetConnectionString ("DbConnection"))); работает эффективно, оставляя только SQLbeginnerContext. Теперь вам не нужно встраивать строку подключения в свой код. Это была очень элементарная ошибка. На решение этой проблемы у меня ушло более 7 часов, и я уже собирался сдаться. спасибо.

Ответы (0)