Установить поле Id при вставке с использованием entity framework - PullRequest
2 голосов
/ 16 июня 2020

Я получаю сообщение об ошибке при попытке вставить объект (весь график, чтобы быть верным) с использованием Entity framework, когда Id имеет некоторое заданное значение, например 6. Оно имеет его, потому что оно было сохранено в другой базе данных, и я могу вручную установить это для каждого элемента в списке и для каждого элемента в подсписке et c et c. Но я должен сделать это для каждого элемента и для каждого запроса. Я хотел бы иметь уникальный глобальный способ установки поля Id равным нулю, потому что, когда я пытаюсь вставить значение, я получаю ошибку:

Cannot insert explicit value for identity column in table 'XXX' when IDENTITY_INSERT is set to OFF.

Я хочу, чтобы моя база данных установила идентификаторы и заставила структуру объекта игнорировать, если Id установлен на что-либо, кроме 0

Я попытался перекрыть OnSaveChanges, и это кажется слишком поздним, потому что при использовании метода Add или AddRange объект был запущен для отслеживания, и я не могу установить Id для нескольких объектов в списке.

1 Ответ

1 голос
/ 16 июня 2020

В EF Core 3.x вы можете обрабатывать событие ChangeTracker.Tracked и сбрасывать, явно устанавливая автоматически сгенерированный PK для каждого объекта Added, подобного этому (он не должен находиться снаружи, вы можете самостоятельно присоединить контекст db для этого события):


dbContext.ChangeTracker.Tracked += (sender, e) =>
{
    if (!e.FromQuery && e.Entry.State == EntityState.Added && e.Entry.IsKeySet)
    {
        var pk = e.Entry.Metadata.FindPrimaryKey();
        if (pk.Properties.Count == 1)
        {
            var pkProperty = pk.Properties[0];
            if (pkProperty.ValueGenerated == ValueGenerated.OnAdd &&
                defaultValues.TryGetValue(pkProperty.ClrType, out var defaultValue))
            {
                e.Entry.State = EntityState.Detached;
                e.Entry.CurrentValues[pkProperty] = defaultValue;
                var newEntry = e.Entry.Context.Entry(e.Entry.Entity);
                newEntry.State = EntityState.Added;
            }
        }
    }
};

, где defaultValues - это словарь с помеченными 0 (нулевыми) значениями поддерживаемых типов свойств с автоинкрементом (при необходимости вы можете добавить больше):

static readonly Dictionary<Type, object> defaultValues = new Dictionary<Type, object>
{
    { typeof(int), default(int) },
    { typeof(long), default(long) },
    { typeof(decimal), default(decimal) },
};

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

...