Ответ 1
Решение:
try {
context.SaveChanges();
} catch (OptimisticConcurrencyException) {
context.Refresh(RefreshMode.ClientWins, db.Articles);
context.SaveChanges();
}
Я нашел решение для людей, получающих исключение:
Заявление об обновлении, вставке или удалении повлияло на неожиданное количество строк (0). Объекты могут быть изменены или удалены, поскольку объекты загружены. Обновить записи ObjectStateManager.
Но, во всяком случае, у меня вопрос.
Я прочитал тему: Entity Framework: "Сохранить заявку на обновление, вставку или удаление повлияло на неожиданное количество строк (0)." Чтобы VMAtm, Роберт Харви
В моем случае я имел, например, таблицы статей:
Articles
------------
article_id
title
date_cr
date_mod
deleted
И у меня был триггер:
create trigger articles_instead_of_insert
on articles instead of insert
as
SET NOCOUNT ON;
insert into articles(
article_id,
title,
date_cr,
date_mod,
deleted
)
select
user_id,
title,
isnull(date_cr, {fn NOW()}),
isnull(date_mod, {fn NOW()}),
isnull(deleted, 0)
from inserted;
go
Когда я удаляю этот триггер, я не получаю это исключение. Таким образом, этот триггер является проблемой. И теперь у меня есть вопрос - почему? Должен ли я что-то сделать?
Решение:
try {
context.SaveChanges();
} catch (OptimisticConcurrencyException) {
context.Refresh(RefreshMode.ClientWins, db.Articles);
context.SaveChanges();
}
Лучше вы обновите свой метод сохранения, как это..... Если вы вызываете метод контекста сущности savechange()
после каждого объекта addobject и deleteobject или модификации:
public void Save(object entity)
{
using (var transaction = Connection.BeginTransaction())
{
try
{
SaveChanges();
transaction.Commit();
}
catch (OptimisticConcurrencyException)
{
if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Deleted || ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Modified)
this.Refresh(RefreshMode.StoreWins, entity);
else if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Added)
Detach(entity);
AcceptAllChanges();
transaction.Commit();
}
}
}
Это потому, что у вас есть SET NOCOUNT ON
.
Заявление EF SQL, которое он генерирует ALWAYS, добавляет предложение where @@ROWCOUNT > 0 and [ID] = scope_identity()
(например).
Обратите внимание на предложение where @@ROWCOUNT > 0
. Снимите инструкцию SET NOCOUNT ON
, и она должна работать.
Возможная проблема: Вы поместили ReadOnlyAttribute в метаданные ключевых слов сущностей, что приводит к тому, что его значение становится равным нулю
[DisplayName("Student ID")]
[ReadOnly(true)]
public int StudentID { get; set; }
Решение: Удалить атрибут ReadOnlyAttribute
[DisplayName("Student ID")]
public int StudentID { get; set; }
У меня была та же проблема, это сообщение об ошибке довольно мистифицирует. Ответ от webtrifusion помог мне. См. Entity Framework: "Заявление об обновлении, вставке или удалении повлияло на неожиданное количество строк (0)."
Оказывается, я забыл добавить "Id: 0" в JSON на стороне клиента.
У меня был параметр InsertAsync EntityState для модификации, реализующий шаблон хранилища. Когда Debugging я обнаружил идентификатор объекта, был 0
public async Task InsertAsync(T entity)
{
dbContext.Entry(entity).State = EntityState.Modified;
await dbContext.SaveChangesAsync();
}
Изменение состояния объекта в добавленное исправленное.
dbContext.Entry(entity).State = EntityState.Added;
Я нашел эту ошибку, когда я обновляю объект и забыл передать значение основного ключа....
Таким образом, Entity может обновлять запись со ссылкой с помощью основного ключа
Решение. Проверьте, не изменилось ли значение первичного ключа или нет, чтобы обновить данную запись.:)
У меня была такая же ошибка, после чего я понял, что забыл заданный первичный ключ в таблице и установил значения приращения...
В моем случае необходимо установить атрибут DatabaseGenerated при первом использовании пользовательского кода
public class Car
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Model { get; set; }
public DateTime Registered { get; set; }
}
или же
Отключение идентификатора для первичных числовых ключей В следующем примере для свойства DepartmentID устанавливается значение System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None, чтобы указать, что значение не будет сгенерировано базой данных.
modelBuilder.Entity<Department>().Property(t => t.DepartmentID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
см. https://docs.microsoft.com/zh-tw/ef/ef6/modeling/code-first/conventions/custom
и https://docs.microsoft.com/zh-tw/ef/ef6/modeling/code-first/fluent/types-and-properties
Сначала используя код структуры Entity Framework,
используя (MyDbContext db = new MyDbContext()) {..
Добавление этого значения после строки использования:
db.Configuration.ValidateOnSaveEnabled = true;