Немного фона. Я использую:
и я использую это простое объявление последовательности HiLo в своем контексте.
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.ForNpgsqlUseSequenceHiLo();
}
Что создает мои файлы миграции следующим образом:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateSequence(
name: "EntityFrameworkHiLoSequence",
incrementBy: 10);
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SequenceHiLo),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
// other tables code goes here... All key has
// .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SequenceHiLo)
}
Все работает, но HiLo присваивает странные ID (но все же уникальные). Как странно? Позволь мне объяснить. Например:
у меня есть столы
И я делаю простое семя для базы данных, которое присваивает идентификаторы следующим образом:
Заказы:
ЗаказЭлемент:
Роли:
Таким образом, похоже, что он разделил HiLo для всех столов. Я думал, что это HiLo за стол.
Также я получаю сообщение об ошибке, когда использую чистую новую миграцию и делаю:
dotnet ef database drop && dotnet ef database updateУ меня ошибка (перевод с польского на английский):
42P07: relation "EntityFrameworkHiLoSequence" already exist
@ОБНОВИТЬ
Благодаря @jpgrassi я нашел решение для странных идентификаторов. Я сделал имя HiLo для каждой модели. Это выглядит так:
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<OrderItem>()
.Property(b => b.Id)
.ForNpgsqlUseSequenceHiLo("OrderItemsHiLo");
modelBuilder.Entity<Order>()
.Property(b => b.Id)
.ForNpgsqlUseSequenceHiLo("OrdersHiLo");
// More sequences goes below...
}
Теперь все звучит логично. Но... у меня новая ошибка:
42P07: relation "OrderItemsHiLo" already exist
Мой Up раздел:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateSequence(
name: "OrderItemsHiLo",
incrementBy: 10);
// more code...
}
И в моем разделе Down в миграции у меня есть:
migrationBuilder.DropSequence(name: "OrderItemsHiLo");
Мой вопрос: Почему эта ошибка возникает при чистой миграции и как от нее избавиться?
@ОБНОВИТЬ
Я просто удалил эту строку, и это решило мою вторую проблему. Глупый я...
_context.Database.EnsureCreatedAsync();
Хм... Я никогда не думал об этом. Я постараюсь и дам вам знать :)
Ошибка все еще возникает, файл миграции выглядит так же, все тесты пройдены и в основном все то же самое, что и при использовании modelBuilder.ForNpgsqlUseSequenceHiLo();. Также мне нужен base.OnModelCreating(modelBuilder); для идентификации
Проблема миграции: что делается в Down миграции? EntityFrameworkHiLoSequence тоже выпал? Теперь генерация идентичности, я понятия не имею.. но что вы имеете в виду, что вам это нужно для идентичности? Под идентичностью вы имеете в виду колонку идентичности? Если да, то зачем вам последовательность HiLo? Немного запутался сейчас.
@jpgrassi Во-первых, я обновил свой вопрос. Во-вторых, под идентификацией я подразумеваю Удостоверение Майкрософт. Извините за умственный ярлык В-третьих, спасибо за вашу помощь. Вы частично решили мою проблему.
Вместо того, чтобы запускать миграцию автоматически, попробуйте сгенерировать для вас скрипт SQL: запустите dotnet ef migrations script <hilo sequence migration> <older migration> -o migration.sql и посмотрите, что сгенерировал SQL. Очевидно, есть какая-то проблема с тем, что последовательность не сбрасывается. Может быть, это не в той же схеме, что и база данных?
Давайте продолжить обсуждение в чате.
Я добавил ответ, чтобы другие тоже могли извлечь выгоду. Взгляните на него, а также на образец приложения, который я создал.





Несмотря на то, что OP отредактировал сообщение и в значительной степени решил проблему с моей помощью, я опубликую фактический ответ, чтобы другие, столкнувшиеся с той же «проблемой», могли извлечь выгоду.
По поводу "странного" сгенерированного идентификатора. Вам нужно создать одну последовательность для каждого объекта, чтобы они не «делили» идентификаторы. Подробнее о документации провайдера: Генерация автоинкремента HiLo
Переопределите OnModelCreating в своем классе DbContext и добавьте это:
modelBuilder.Entity<OrderItem>()
.Property(b => b.Id)
.ForNpgsqlUseSequenceHiLo($"Sequence-{nameof(OrderItem)}");
// same for others you want a sequence
Повторно добавьте миграции, и у вас должно получиться что-то вроде этого:
migrationBuilder.CreateSequence(
name: "Sequence-OrderItem",
incrementBy: 10);
// Order entity code ommited
Id = table.Column<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SequenceHiLo)
Теперь о вашем «втором» вопросе о невозможности воссоздать базу данных после запуска dotnet ef database drop Я не смог ее воспроизвести. Я создал образец приложения ASP.NET Core, в котором используется EF Core с PostegreSQL, и я смог нормально удалить/создать базу данных.
Я отправил приложение в свою учетную запись GitHub, так что вы можете клонировать его и попробовать сами: efcore-postgres-hilo-последовательность
Я не очень хорошо знаком с использованием PostgreSQL с EF, но что происходит вместо того, чтобы добавлять
ForNpgsqlUseSequenceHiLoв широком смысле, вы добавляете его для каждой отдельной сущности? Кроме того, не уверен насчет этого вызоваbase.OnModelCreating(modelBuilder);. В документах не указано npgsql.org/efcore/…