Таблица, не созданная с помощью DbContext (Недопустимое имя объекта)

#c# #api #asp.net-core

Вопрос:

Я хочу выучить ASP .СЕТЬ с Blazor, поэтому я пытаюсь создать небольшой проект с веб-сборкой Blazor и API, чтобы установить соединение между интерфейсом и базой данных. Моя проблема в том, что я создал первый DbContext (с контроллером моделью), и он хорошо работает. Но когда я пытаюсь создать второй DbContext (с контроллером моделью), таблица не создается в базе данных, потому что context.Database.EnsureCreated возвращает значение false. (но первая таблица с именем DisplayableЭлементы создана идеально !)

Здесь вы можете посмотреть Program.cs :

 using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Portfolio.API.Contexts;

namespace Portfolio.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            CreateDbIfNotExists(host);

            host.Run();
            CreateHostBuilder(args).Build().Run();
        }

        private static void CreateDbIfNotExists(IHost host)
        {
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var contextDisplayableElement = services.GetRequiredService<DisplayableElementContext>();
                    Initializer.DbInitializer.InitializeDisplayableElements(contextDisplayableElement);
                    var contextUser = services.GetRequiredService<UserContext>();
                    Initializer.DbInitializer.InitializeUsers(contextUser);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred creating the DB.");
                }
            }
        }

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

 

Здесь вы можете увидеть Startup.cs :

 using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Portfolio.API.Contexts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Portfolio.API
{
    public class Startup
    {
        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

        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.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy(name: MyAllowSpecificOrigins,
                                  builder =>
                                  {
                                      builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
                                  });
            });


            services.AddDbContext<UserContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddDbContext<DisplayableElementContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddControllers(options => options.SuppressAsyncSuffixInActionNames = false);
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Portfolio.API", Version = "v1" });
            });
        }

        // 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();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Portfolio.API v1"));
            }

            app.UseCors(MyAllowSpecificOrigins);

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

 

Here you can see UserContext.cs :

 using Microsoft.EntityFrameworkCore;
using Portfolio.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Portfolio.API.Contexts
{
    public class UserContext : DbContext
    {
        public UserContext(DbContextOptions<UserContext> options) : base(options)
        {
        }

        public DbSet<User> Users { get; set; }
    }
}

 

Here you can see User.cs :

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Portfolio.Models
{
   public class User
   {
       public long Id { get; set; }
       public string Login { get; set; }
       public string Password { get; set; }
       public int NumberConnectionTry { get; set; }

       public User(string login, string password)
       {
           this.Login = login;
           this.Password = password;
       }

       public User()
       { }
   }

 

Here you can see appsettings.json :

 {
 "ConnectionStrings": {
   "DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=Portfolio;Trusted_Connection=True;MultipleActiveResultSets=true"
 },
 "Logging": {
   "LogLevel": {
     "Default": "Information",
     "Microsoft": "Warning",
     "Microsoft.Hosting.Lifetime": "Information"
   }
 },
 "AllowedHosts": "*",
 "ApiKey": "localhostKey"
}

 

Здесь вы можете увидеть DbInitializer.cs:

 using Portfolio.API.Contexts;
using Portfolio.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Portfolio.API.Initializer
{
   public class DbInitializer
   {
       public static void InitializeDisplayableElements(DisplayableElementContext context)
       {
           context.Database.EnsureCreated();

           // Look for any displayable element.
           if (context.DisplayableElements.Any())
           {
               return;   // DB has been seeded
           }

           var elements = new DisplayableElement[]
           {
               new DisplayableElement("software", 0, "Visual Studio 2019", 3)
           };
           foreach (DisplayableElement dis in elements)
           {
               context.DisplayablesElements.Add(dis);
           }
           context.SaveChanges();
       }

       public static void InitializeUsers(UserContext context)
       {
           var toto = context.Database.EnsureCreated();
           if (context.Users.Any())
           {
               return;   // DB has been seeded
           }
           var elements = new User[]
           {
               new User("toto", "toto")
           };
           foreach (User u in elements)
           {
               context.Users.Add(u);
           }
           context.SaveChanges();

       }
   }


}

 

У вас есть решение для решения этой проблемы, пожалуйста ?
Если вам нужен еще один файл моего проекта, не стесняйтесь спрашивать…

Спасибо, что нашли время прочитать этот выпуск.

Ответ №1:

На основе документации EnsureCreated .

В приведенном выше тесте, предполагая, что база данных не существует, для первого запуска теста EnsureCreated создаст базу данных и пройдет тест. Но для любых последующих запусков база данных уже существует, поэтому EnsureCreated возвращает значение false. Возможно, вы хотите использовать EnsureDeletedbeforeEnsureCreated, чтобы убедиться, что база данных удалена, чтобы вы могли проверить ее фактическое создание.

Комментарии:

1. Здравствуйте, спасибо за ваш ответ и извините за мой поздний ответ, у меня возникли проблемы с подключением к Интернету. Проблема в том, что моя таблица не создана (если я покажу базу данных в visual studio 2019, я не смогу увидеть эту таблицу). Кроме того, файл с моей таблицей не создается в моей папке пользователя. Поэтому я думаю, что моя проблема исходит из другого места.

Ответ №2:

Обновление : На самом деле, я не могу создать два DbContext для одной и той же базы данных. Итак, я поместил весь свой набор баз данных в один и тот же класс, как это :

 using Microsoft.EntityFrameworkCore;
using Portfolio.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Portfolio.API.Contexts
{
    public class PortfolioContext : DbContext
    {
        public PortfolioContext(DbContextOptions<PortfolioContext> options) : base(options)
        {
        }

        public DbSet<DisplayableElement> DisplayableElements { get; set; }
        public DbSet<User> Users { get; set; }
    }
}
 

Я надеюсь, что это поможет вам, если у вас та же проблема, что и у меня !