EF 6 вызывает INSERT вместо UPDATE - PullRequest
0 голосов
/ 26 июня 2018

Это может быть повторяющийся вопрос, но большой поиск слов в названии только принес мне много несвязанных результатов.

У меня есть объект, который примерно настроен так:

public abstract class A
{
    public GUID AId { get; set; }

    public string SomeProperty { get; set; }
}

public class B : A
{
    public string SomeOtherProperty { get; set; }
}

Контекст имеет public DbSet<B> BInstances { get; set; } для B объектов.В OnModelCreating для сопоставления A установлено значение игнорируется, а B сопоставляется с таблицей с именем TableB.

Поле AId не генерируется автоматически (не поле идентификации), но оно установлено как первичный ключ как в базе данных, так и в отображении.В базе данных поле определяется как ненулевое uniqueidentifier без значения по умолчанию.

Во время выполнения я загружаю экземпляр B, используя его ключ (_token это просто CancellationToken):

var b = await (dbCtx.BInstances.FirstOrDefaultAsync(e => e.AId), _token));

Затем устанавливается свойство b, и я пытаюсь сохранить его обратно в базу данных:

b.SomeOtherProperty = "some new text";
await (dbCtx.SaveChangesAsync(_token));

На этом этапе я получаю Нарушение ограничения PRIMARY KEY Ошибка из базы данных, заявив, что значение AId не может быть вставлено, потому что это будет дубликат.Конечно, идентификатор уже есть в базе данных, я загрузил сущность оттуда, используя идентификатор.По какой-то причине EF генерирует оператор INSERT, а не UPDATE, и я не понимаю, почему.

Когда я проверяю dbCtx.Entry(b).State, он уже установлен на EntityState.Modified.Я в растерянности - кто-то может указать, что я делаю не так?У меня никогда не было проблем с обновлением сущностей, но я не использовал EF с первичными ключами GUID (обычно я использую long первичные ключи).

Я использую EF 6 и .NET Framework 4.7.1.

Ответы [ 2 ]

0 голосов
/ 12 июля 2018

Спасибо всем за предложения - это оказалось проблемой картографии, которую я вызвал.

В моем вызове OnModelCreating() я вызвал MapInheritedProperties() для типа, который не наследовал от базового класса (кроме, конечно, object) - это, похоже, вызвало проблему.Другие сущности, которые совместно используют базовый класс, прекрасно работали с вызовом сопоставления.

Я также вызывал ToTable() непосредственно против класса сущности - это нарушило мое сопоставление таблиц по причинам, которые я не понимаю.Как только я переместил этот вызов внутрь Map(), он начал работать, как и ожидалось.

Итак, я перешел от этого:

entity.ToTable("tablename");

к этому:

entity.Map(m => m.ToTable("tablename"));

врешить проблему.

Надеюсь, это будет полезно для будущих читателей.

0 голосов
/ 26 июня 2018

попробуйте

b.SomeOtherProperty = "some new text";
dbCtx.BInstances.AddOrUpdate(b);
await (dbCtx.SaveChangesAsync(_token));

AddorUpdate обновит ваш экземпляр b, если он уже добавлен.

...