Ошибки с созданием таблиц по первой модели кода с npgsql

Проблема с созданием таблиц по первой модели кода с npgsql

Создание базы данных должно работать с версии 2.2.0-бета1: "Дэвид Карлаш добавил поддержку EFMigration и создание базы данных в EF6+. Теперь можно запускать проекты Code First без необходимости заранее создавать базу данных. EntityFramework и Npgsql позаботятся об этом. Эмиль Леннгрен добавил поддержку многих недостающих функций EntityFramework. " https://www.nuget.org/packages/Npgsql/2.2.0-beta1

Но когда я попытался сделать это, я столкнулся с проблемами.

Во-первых, я сделал простой проект, который работает с SqlServer: я создал проект Asp.Net MVC (VS2013) и добавил немного кода:

public class Movie
{
    public int ID { get; set; }
    public string Title { get; set; }
}

public class MovieDBContext : DbContext
{
    public DbSet<Movie> Movies { get; set; }
}

public class MovieDBInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext>
{
}

public class HomeController : Controller
{
    private MovieDBContext db = new MovieDBContext();

    public ActionResult Index()
    {
        List<Movie> objs = db.Movies.ToList();
        return View(objs);
    }

WebConfig:

  <connectionStrings>
    <add name="MovieDBContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=MovieCreateDbInSql;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\MovieDB.mdf" providerName="System.Data.SqlClient" />  
  </connectionStrings>

  <entityFramework>
    <contexts>
      <context type="MovieCreateDbInSql.Models.MovieDBContext, MovieCreateDbInSql">
        <databaseInitializer type="MovieCreateDbInSql.Models.MovieDBInitializer, MovieCreateDbInSql" />
      </context>
    </contexts>

    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>

При запуске проекта создается база данных MovieDB.

Все работает.

Мы можем увидеть эту базу данных в папке App_Data в проекте. Хорошо.

Затем я попытался сделать то же самое с npgsql.

  1. Добавить библиотеки:

EntityFramework6.Npgsql.dll (версия 3.1.0.0)

Npgsql.dll (версия 3.1.2.0)

2.

Чем изменить WebConfig:

  <connectionStrings><add name="MovieDBContext" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=postgres000;" providerName="Npgsql" /></connectionStrings>

  <entityFramework>
    <contexts>
      <context type="MovieCreateDbInSql.Models.MovieDBContext, MovieCreateDbInSql">
        <databaseInitializer type="MovieCreateDbInSql.Models.MovieDBInitializer, MovieCreateDbInSql" />
      </context>
    </contexts>
    <defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql" />
    <providers>
      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql"></provider>
    </providers>
  </entityFramework>

  <system.data>
    <DbProviderFactories>
      <remove invariant="Npgsql" />
      <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql"
           type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
  </system.data>

Начните. Ошибка:

System.NotSupportedException was unhandled by user code
  HResult=-2146233067
  Message=Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.
  Source=EntityFramework

Но такой конфигурации было достаточно для SqlServer!

Хорошо. Попробуй это:

EF5 Получение этого сообщения об ошибке: Невозможно проверить совместимость модели, поскольку база данных не содержит метаданных модели.

1.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}

Не очень помогает Ошибка та же

  1. открытый класс MovieDBInitializer: DropCreateDatabaseAlways { }

Новая ошибка:

Npgsql.PostgresException was unhandled by user code
  HResult=-2147467259
  Message=55006: база данных "postgres" занята другими пользователями
  Source=Npgsql
  ErrorCode=-2147467259
  BaseMessage=база данных "postgres" занята другими пользователями
  Code=55006
  Detail=Эта база данных используется ещё в 1 сеансе.
(error 55006 database is being accessed by other user)

Эта ошибка тоже не хорошо. Насколько я понимаю, эта ошибка связана с тем, что мы имеем серьезную базу данных posgresql в отличие от примитива localdb.sql. И удаление операции db в postgresql не так просто, как в localdb.sql.

Я нашел несколько ссылок на эту ошибку:

https://groups.google.com/forum/

Удалить базу данных, к которой обращаются другие пользователи?

  1. Проблемы с первой установкой кода npgsql и Entity Framework

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MovieDBContext>(null);
    }
    

Та же ошибка снова:

System.NotSupportedException was unhandled by user code
  HResult=-2146233067
  Message=Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.
  Source=EntityFramework

Что я должен сделать, чтобы иметь возможность создавать таблицы по первой модели кода?

Конечно, я могу создать базу данных в SqlServer и затем конвертировать скрипты в postgresql, но я хочу сделать это с помощью npgsql.

2 ответа

Библиотеки, которые я использую:

  • EntityFramework.6.1.3
  • EntityFramework6.Npgsql.3.1.0
  • Npgsql.3.1.3

Контекст моей базы данных:

public class CustomContext : DbContext
{

    public CustomContext()
        : base("name=CustomContext")
    {
        Database.SetInitializer(
            new MigrateDatabaseToLatestVersion<CustomContext, Configuration>());
    }

    public DbSet<Movie> Movies { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Change schema name from "dbo" => "public" for all entities (except MigrationHistory).
        // MigrationHistory schema name is modified in custom HistoryContext 
        modelBuilder.Types().Configure(c => c.ToTable(c.ClrType.Name, "public"));
    }

}

В таблице истории миграции по умолчанию установлена ​​схема "dbo". Если вы хотите, чтобы он был в другой схеме (например, общедоступной), вам нужно создать собственный HistoryContext.
В настоящее время невозможно установить схему по умолчанию с modelBuilder.HasDefaultSchema("public") при использовании автоматической миграции (AFAIK).

public class CustomHistoryContext : HistoryContext
{
    public CustomHistoryContext(DbConnection existingConnection, string defaultSchema) 
       : base(existingConnection, defaultSchema)
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Change schema from "dbo" to "public"
        modelBuilder.Entity<HistoryRow>()
                    .ToTable(tableName: "__MigrationHistory", 
                             schemaName: "public");
    }
}

Наконец, мой класс конфигурации миграции выглядит так:

internal sealed class Configuration : DbMigrationsConfiguration<CustomContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;

        // Setting custom historyContext factory.
        // Used for modify __MigrationHistory table schema name from "dbo" to "public"
        this.SetHistoryContextFactory("Npgsql",
            (connection, defaultSchema) => 
                 new CustomHistoryContext(connection, defaultSchema));

    }

    protected override void Seed(CustomContext context)
    {
        //  This method will be called after migrating to the latest version.
    }
}

После этих шагов автоматические коды первой миграции работают корректно.

Однако, здесь есть немного больше деталей.

У меня есть занятия:

public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime IssueDay { get; set; }
public decimal EarnedMoney { get; set; }
public virtual ICollection<Actor> Actors { get; set; }
}
public class Actor
{
public int ID { get; set; }
public int MovieID { get; set; }
public DateTime BirthDay { get; set; }
public string Name { get; set; }
}

И я получил сценарии:

CREATE TABLE "Movie"
(
"ID" serial NOT NULL,
"Title" text,
"IssueDay" timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00'::timestamp without time zone,
"EarnedMoney" numeric(18,2) NOT NULL DEFAULT 0,
CONSTRAINT "PK_public.Movie" PRIMARY KEY ("ID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE "Movie"
OWNER TO postgres;

CREATE TABLE "Actor"
(
"ID" serial NOT NULL,
"MovieID" integer NOT NULL DEFAULT 0,
"Name" text,
"BirthDay" timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00'::timestamp without time zone,
CONSTRAINT "PK_public.Actor" PRIMARY KEY ("ID"),
CONSTRAINT "FK_public.Actor_public.Movie_MovieID" FOREIGN KEY ("MovieID")
REFERENCES "Movie" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
ALTER TABLE "Actor"
OWNER TO postgres;

CREATE INDEX "Actor_IX_MovieID"
ON "Actor"
USING btree
("MovieID");

И эти сценарии требуют дополнительной обработки, конечно.

Вот почему, в общем, нет никакой разницы: генерировать скрипты непосредственно в postgres или генерировать в sqlServer, а затем конвертировать в postgres, например, с помощью Navicat…

Другие вопросы по тегам