我正在尝试在MSTest单元测试中更新Postgresdatabase上的数据。在每次测试之前,我都删除所有书籍并创建一些新书,以确保测试的正确数据:
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。有关了解和处理乐观并发异常的信息。”
我正在使用Postgres提供的乐观并发,如其网站https://www.npgsql.org/efcore/modeling/concurrency.html所述,在我的书实体上的OnModelCreating中调用UseXminAsConcurrencyToken()
我该如何解决这个问题?
当您调用时UseXminAsConcurrencyToken
,这xmin
会在您的实体上设置一个属性,该属性将保存xmin
PostgreSQL中的列的值(该值是自动生成的等)。由于您的实际Book CLR类型没有xmin成员,因此配置了shadow属性。这意味着该列的值存储在上下文中,而不存储在CLR实例中。
因此,将加载的CLR实例从一个上下文移动到另一个上下文时,该值会丢失-因为它存储在上下文中。因此,当您尝试在新的上下文中更新它时,该值默认为0-这是不正确的-并且会出现异常。
要解决此问题,您可以:1.只需xmin
在Book类上定义uint类型的属性。这将导致使用它而不是阴影属性,因此它将在实例之间持久存在。2.在新的上下文中重新加载实体,以便重新加载值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句