ASP.NET 5, EF 7 и SQLite - SQLite Ошибка 1: "нет такой таблицы: блог"

Я последовал за Руководством по ASP.NET 5 о Entity Framework 7, и я заменил MicrosoftSqlServer на Sqlite, единственное различие в коде - в Startup.cs

services.AddEntityFramework()
    .AddSqlite()
    .AddDbContext<BloggingContext>(options => options.UseSqlite("Filename=db.db"));

Когда я запускаю веб-сайт и перебираюсь в/Блоги, я получаю сообщение об ошибке:

Microsoft.Data.Sqlite.SqliteException не обрабатывается кодом пользователя
ErrorCode = -2147467259 HResult = -2147467259 Сообщение = SQLite Ошибка 1: "нет такой таблицы: Блог" Source = Microsoft.Data.Sqlite
SqliteErrorCode = 1 StackTrace:        в Microsoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC(Int32 rc, Sqlite3Handle db)        в Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior поведение)        в Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior поведение)        в System.Data.Common.DbCommand.ExecuteReader()        в Microsoft.Data.Entity.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()        в System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()        в System.Linq.Enumerable.d__1`2.MoveNext()        в System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()        в Microsoft.Data.Entity.Query.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()        в System.Collections.Generic.List`1..ctor(коллекция IEnumerable`1)        в System.Linq.Enumerable.ToList [TSource] (источник IEnumerable`1)        в EFGetStarted.AspNet5.Controllers.BlogsController.Index() в d:\arthur\documents\visual studio 2015\Projects\EFGetStarted.AspNet5\SRC\EFGetStarted.AspNet5\Контроллеры\BlogsController.cs: регель 18 InnerException:

Я понимаю это, как будто нет таблицы под названием "Блог", но когда я открываю файл .db в DB Browser для SQLite, на самом деле есть таблица под названием "Блог":

Снимок экрана из DB Browser для SQLite с таблицей

Требуется ли SQLite другие изменения в коде или это ошибка в соединителе SQLite для Entity Framework?

Ответ 1

Весьма вероятно, что база данных, фактически открываемая EF, - это не файл, который вы открываете в браузере БД. SQLite использует текущий рабочий каталог процесса, который при запуске в IIS или на других серверах может быть папкой, отличной от каталога исходного кода. (См. Проблемы https://github.com/aspnet/Microsoft.Data.Sqlite/issues/132 и https://github.com/aspnet/Microsoft.Data.Sqlite/issues/55).

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

public class Startup
{
    private IApplicationEnvironment _appEnv;

    public Startup(IApplicationEnvironment appEnv)
    {
        _appEnv = appEnv;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlite()
            .AddDbContext<MyContext>(
                options => { options.UseSqlite($"Data Source={_appEnv.ApplicationBasePath}/data.db"); });
    }
}

Ответ 2

Похоже, что все изменилось, потому что IApplicationEnvironment был заменен на IHostingEnvironment.

Удаление IApplicationEnvironment\IRuntimeEnvironment

public class Startup
{
    private IHostingEnvironment _appHost;

    public Startup(IHostingEnvironment appHost)
    {
        _appHost = appHost;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFrameworkSqlite()
            .AddDbContext<MyContext>(
                options => { options.UseSqlite($"Data Source={_appHost.ContentRootPath}/data.db"); });
    }
}

Ответ 3

У меня была эта проблема на netcoreapp2.0. Есть связанная проблема, которая может быть виновата, но я не хотел ее решать, переходя к ночной сборке.

Решением для меня было создать и передать SqliteConnection вместо использования строки компоновщика.

Итак, для этой настройки:

string id = string.Format("{0}.db", Guid.NewGuid().ToString());

var builder = new SqliteConnectionStringBuilder()
{
    DataSource = id,
    Mode = SqliteOpenMode.Memory,
    Cache = SqliteCacheMode.Shared
};

Составь для DI так:

var connection = new SqliteConnection(builder.ConnectionString);
connection.Open();
connection.EnableExtensions(true);
services.AddDbContext<SomeDbContext>(options => options.UseSqlite(connection));

Ошибка, которую я имел, использовала этот стиль init:

services.AddDbContext<SomeDbContext>(options => options.UseSqlite(builder.ConnectionString));

У моих лесов также есть одноразовый звонок:

var dbContext = serviceScope.ServiceProvider.GetService<SomeDbContext>();
dbContext.Database.OpenConnection();
dbContext.Database.EnsureCreated();

Используя этот подход, все мои экземпляры SomeDbContext использованием SomeDbContext будут указывать на действительную SomeDbContext SQLite, и эта база данных будет иметь автоматически созданную схему в соответствии с моими сущностями.

Ответ 4

Взято из документации EF Core...

Запустить из Visual Studio

Чтобы запустить этот пример из Visual Studio, необходимо вручную установить рабочий каталог в качестве корневого каталога проекта. Если вы не установили рабочий каталог, выдается следующее исключение Microsoft.Data.Sqlite.SqliteException: Ошибка SQLite 1: "нет такой таблицы: блоги".

Чтобы установить рабочий каталог:

  • В обозревателе решений щелкните правой кнопкой мыши проект и выберите " Свойства".
  • Выберите вкладку Debug на левой панели.
  • Установите Рабочий каталог в каталог проекта.
  • Сохраните изменения.

Ответ 5

Я сделал это и все еще не мог загрузить базу данных. Я добавил следующий код в конструктор для контекста базы данных: Database.EnsureCreated();


Теперь мой контекстный файл выглядит так: BoardGameDBContextFile

Он создал новую базу данных на моем новом хостинг-сайте Azure, поэтому, если вам нужно перенести много существующих данных, это не сработает. Это сработало для меня, так что я решил поделиться.