EF Core Postgres DbUpdateConcurrencyException при обновлении отдельных данных - PullRequest
1 голос
/ 22 марта 2020

Я пытаюсь обновить данные в моей базе Postgresd в модульном тесте MSTest. Перед каждым тестом я удаляю все книги и создаю несколько новых, чтобы обеспечить правильные данные для теста:

        private static Book CreateDefaultBook(int i)
        {
            return new Book
            {
                Title = TitlePrefix + i,
                Description = DescriptionPrefix + i
            };
        }

        [TestInitialize]
        public void InitializeContext()
        {
            using (var context = new MampfContext(DbContextOptions))
            {
                foreach (var contextBook in context.Books)
                {
                    context.Entry(contextBook).State = EntityState.Deleted;
                }

                context.SaveChanges();

                for (int i = 1; i <= NumberOfBooks; i++)
                {
                    context.Books.Add(CreateDefaultBook(i));
                }

                context.SaveChanges();
            }
        }

Это отлично работает. Затем я пытаюсь обновить данные в тесте:

        [TestMethod]
        public void UpdateBookTest()
        {
            Book book = null;
            using (var context = new MampfContext(DbContextOptions))
            {
                book = context.Books.FirstOrDefault(r => r.Title == TitlePrefix + 1);
                Assert.IsNotNull(book);
            }

            book.Description = "Changed";

            using (var context = new MampfContext(DbContextOptions))
            {
                var entry = context.Entry(book);
                entry.State = EntityState.Modified;
                context.SaveChanges(); //Exception!
            }

            using (var context = new MampfContext(DbContextOptions))
            {
                var updatedBook = context.Books.FirstOrDefault(r => r.Title == TitlePrefix + 1);
                Assert.IsNotNull(updatedBook);
                Assert.AreEqual("Changed", updatedBook.Description);
            }
        }

Я делаю это в три этапа. Сначала я получаю сущность. Затем я изменяю его, пока он отделен от контекста. Наконец, я присоединяю книгу к новому контексту и устанавливаю измененное состояние и пытаюсь сохранить изменения. Но там я получаю DbUpdateConcurrencyException с сообщением:

"Операция базы данных, как ожидается, затронет 1 строку (и), но фактически затронула 0 строк. Возможно, данные были изменены или удалены с момента загрузки объектов. См. http://go.microsoft.com/fwlink/?LinkId=527962 для получения информации о понимании и обработке оптимистических c исключений параллелизма. "

Я использую параллельный оптимистический c, предоставленный postgres, вызывающий UseXminAsConcurrencyToken () в OnModelCreating на моем Забронировать объект, как описано на его веб-сайте https://www.npgsql.org/efcore/modeling/concurrency.html

Как я могу решить эту проблему?

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Когда вы вызываете UseXminAsConcurrencyToken, это устанавливает свойство xmin для вашей сущности, которое будет содержать значение столбца xmin в PostgreSQL (которое создается автоматически и c.). Поскольку ваш фактический тип Book CLR не имеет члена xmin, свойство shadow настроено; это означает, что значение столбца хранится внутри контекста, а не в экземпляре CLR.

Из-за этого при перемещении загруженного экземпляра CLR из одного контекста в другой это значение теряется, поскольку оно хранится в контексте. Поэтому, когда вы пытаетесь обновить его в новом контексте, значение по умолчанию равно 0 - что неверно - и вы получаете исключение.

Чтобы обойти это, вы можете: 1. Просто определить xmin свойство типа uint в вашем классе Book. Это приведет к тому, что оно будет использоваться вместо свойства shadow, и поэтому оно будет сохраняться во всех случаях. 2. Перезагрузите объект в новом контексте, чтобы перезагрузить значение.

0 голосов
/ 23 марта 2020

Возможно, это проблема реализации в провайдере Npg sql.

Проверяли ли вы свою версию Provider / EF Core /. NET Core? https://github.com/npgsql/efcore.pg/issues/1059

Если вы не запускаете его с подсказками krisztiankocsis и roji, вам нужно начать отслеживать все запросы к базе данных и сравнивать операторы SQL и Состояние модели EF Core.

В качестве альтернативы, может быть, вам может понадобиться сменить поставщика базы данных?

Кстати, этот старый пост может дать вам еще несколько советов: https://github.com/npgsql/efcore.pg/issues/19

...