Подтвердить что ты не робот

Entity Framework автоматически генерирует GUID

Я новичок в EF, поэтому здесь идет. У меня есть класс, который содержит следующие

public class EmailTemplate
{
    public Guid Id { get; set; }

    [MaxLength(2000)]
    public string Html { get; set; }
}

Вот мой класс отображения

class EmailMapper : EntityTypeConfiguration<EmailTemplate>
    {
        public EmailMapper()
        {
            ToTable("EmailTemplate");

            HasKey(c => c.Id);
            Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(c => c.Id).IsRequired();
        }
    }

Я пытаюсь вызвать DbContext.SaveChanges(), но я получаю следующую ошибку:

Сведения об исключении: System.Data.SqlClient.SqlException: не удается вставить значение NULL в столбец "Id", таблицу "AutoSendConnection.dbo.EmailTemplates"; столбец не допускает нулей. INSERT не работает.

Что я делаю неправильно? Почему EF автоматически не создаст уникальный GUID?

4b9b3361

Ответ 1

Просто оформите поле Id в своем классе EmailTemplate, как показано ниже, и SQL Server автоматически сгенерирует значение для вставки.

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; set; }

Вы также можете удалить свой класс Mapper, поскольку он больше не нужен.

Ответ 2

Если вы используете ядро .Net, это должно работать на вас...

Используйте свободный API

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Node>().Property(x => x.ID).HasDefaultValueSql("NEWID()");
}

или же

modelBuilder.Entity<Student>().Property(p => p.StudentID)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Вот более полный Шпаргалка для структуры лица

Ответ 3

Задайте значение sql по умолчанию для поля "newsequentialid()" в конфигурации сопоставления.

Ответ 4

Вы также можете установить значение по умолчанию для IDID как NewID() в Sql Server и передать идентификатор GUID как null

Я использовал это в SSMS.

Ответ 5

Я предпочитаю выходить из базы данных, чтобы автоматически генерировать идентификатор, например, следующую схему:

CREATE TABLE [dbo].[MyTable](
    [MyId] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Booking_BookingId]  DEFAULT (newsequentialid())
    )

Затем в отображении кода сначала я указываю следующее, чтобы сообщить Entity Framework, что база данных позаботится о создании значения при вставке.

Property(a => a.MyId).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Ответ 6

Обращаясь к другим ответам здесь

Кажется, ни один из этих вариантов не работает, и я снова и снова задавал вопросы с командой EF на github...

https://github.com/aspnet/EntityFramework6/issues/762

... по какой-то причине команда разработчиков EF, кажется, думает, что это "работает по замыслу", и неоднократно закрывает заявки, ставя под сомнение эту "ошибку".

Объяснение команды EF

По какой-то причине они, похоже, думают, что "генерация направляющих в SQL считается не лучшей практикой и что для того, чтобы ключи были доступны немедленно, мы должны генерировать ключи в коде приложения".

Проблема здесь, конечно, заключается в том, что таблицы с большим количеством пользователей рискуют предпринять дальнейшие деловые действия, используя недопустимый ключ.

В моем случае это может нарушить некоторые очень сложные многосерверные транзакции DTC, поэтому я не верю, что совет от MS был правильным.

Мой ответ (который на самом деле работает)

Короче говоря, я решил эту проблему, "взломав вручную" созданную миграцию после ее создания...

EF код первой миграции, БД генерирует ключи guid

Чтобы процитировать другой вопрос, ответ...

Сгенерируйте сценарий миграции, как обычно, поместив оба атрибута в свойство ключа следующим образом...

public class Foo
{
     [Key]
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public Guid Id { get; set; }
}

.. декларативно говоря, сущность теперь верна.

Сгенерированная им миграция будет выглядеть примерно так:

CreateTable ("dbo.Foos", c => new {Id = c.Guid(nullable: false),...}).PrimaryKey(t => t.Id)...;

... Я не смог определить причину, но в некоторых ситуациях это сработает, а в других - нет (запустите миграцию, выполните вставку для проверки).

Если это не удастся, откатите миграцию назад, затем измените ее, чтобы прочитать что-то вроде...

CreateTable(
    "dbo.Foos",
    c => new
        {
            Id = c.Guid(nullable: false, defaultValueSql: "newid()"),
            ...
        })
    .PrimaryKey(t => t.Id)
    ...;

... дополнительный код говорит SQL генерировать ключ, как мы и ожидали.

Как правило, я бы применил это изменение все время по соображениям согласованности, и это означает, что ваши миграции сразу покажут, какие именно ключи генерируются в БД.

Ответ 7

Обновление основного ядра Framework:

Нет необходимости использовать [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
Нет необходимости использовать fluent API

EF Core автоматически позаботится об этом и генерирует идентификатор для первичного ключа

Пример:

public class DummyEntity
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

}

Посев

    _context.DummyEntities.Add(new DummyEntity
    {
        FirstName = "Abc",
        LastName = "Def",
        Postion = "User",
    });

    _context.SaveChanges();