Проверьте, существует ли уже запись в Entity Framework - PullRequest
0 голосов
/ 30 апреля 2020

Хорошо, я знаю, что этот вопрос звучит глупо в названии, но выслушайте меня.

Я делаю API в ASP. NET, используя Entity Framework. Проблема в том, что он не поддерживает автоматическую генерацию UUID в качестве идентификаторов и автоматических столбцов c CreatedAt и UpdatedAt. Я следовал этому руководству: https://www.entityframeworktutorial.net/faq/set-created-and-modified-date-in-efcore.aspx

Чтобы преодолеть эту проблему, я создал базовый класс под названием BaseEntity, который я использую во всех своих моделях. Выглядит это так:

public class BaseEntity
{
    public Guid Id { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
}

Все мои модели просто реализуют его, как в следующем примере: public class User : BaseEntity {}.

Теперь я переопределил метод SaveChanges() поверх Entity Framework, чтобы разрешить обработку собственного кода для автоматического заполнения CreatedAt и обновления столбцов UpdatedAt. Теперь я также хочу автоматически сгенерировать UUID, но, как вы все знаете, они не всегда на 100% уникальны. Поскольку это будет крупномасштабный проект, мне действительно нужно это проверить, хотя шансы очень малы.

Мой переопределенный SaveChanges() метод выглядит следующим образом:

public override int SaveChanges()
{
    // Get the entries wether they were modified. This happens, so anything that wasn't changed, won't be updated in 'UpdatedAt'
    var entries = ChangeTracker
        .Entries()
        .Where(e => e.Entity is BaseEntity && (
            e.State == EntityState.Added
            || e.State == EntityState.Modified));

    // Foreach over all database entries
    foreach (var entityEntry in entries)
    {
        // UpdatedAt should always be updated, no matter what (if there is a change)
        ((BaseEntity) entityEntry.Entity).UpdatedAt = DateTime.Now;

        // If the entry is new, also insert 'Id' and 'CreatedAt'
        if (entityEntry.State == EntityState.Added)
        {
            ((BaseEntity) entityEntry.Entity).CreatedAt = DateTime.Now;

            ((BaseEntity) entityEntry.Entity).Id = Guid.NewGuid();
            // TODO: Here I want to automatically generate a UUID for a new model. But how?
        }
    }

    // Now return to the base method
    return base.SaveChanges();
}

Теперь мой вопрос: как я могу проверить, есть ли UUID в базе данных, и сгенерировать другой, если это необходимо? Есть комментарий TODO о месте, где это нужно сделать. У меня уже есть небольшой предварительный просмотр кода, который должен генерировать UUID над комментарием.

Надеюсь, кто-нибудь может мне помочь.

1 Ответ

1 голос
/ 30 апреля 2020

Один из вариантов - украсить свой идентификатор следующим образом:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]

И тогда вам не нужно беспокоиться о его уникальности. БД позаботится об этом на вставке. Я думаю, что он использует команду newsequential Id в sql, а не newid, когда вы делаете это.

Вы можете подтвердить это после запуска новой миграции go в sql и проверить значение по умолчанию для столбца id , если он newid, обязательно измените его на newsequentialid, и все будет в порядке.

...