问题描述
|
我在管理实体框架的并发性时遇到问题。
我定义了一个Person类
(我只会显示有趣的部分)
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid? CategoryId { get; set; }
public virtual Category Category { get; set; }
public byte[] TimeStamp { get; set; }
}
和一个配置类
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration() : base()
{
HasKey(p => p.Id);
Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.TimeStamp)
.IsConcurrencyToken()
.HasColumnType(\"timestamp\")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
}
同样,我定义了Category类和相应的类
配置类
public class Category
{
public Guid Id { get; set; }
public string Title { get; set; }
public byte[] TimeStamp { get; set; }
}
public class CategoryConfiguration : EntityTypeConfiguration<Category>
{
public CategoryConfiguration() : base()
{
HasKey(c => c.Id);
Property(c => c.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(c => c.TimeStamp)
.IsConcurrencyToken()
.HasColumnType(\"timestamp\")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
}
在CommitChanges方法中,我捕获了DbUpdateConcurrencyException
例外,并采用“数据库获胜”策略,我从数据库重新加载了实体。
public int CommitChanges()
{
ret = -1;
try
{
ret = _context.SaveChanges();
}
catch (DbUpdateConcurrencyException e)
{
(e as DbUpdateConcurrencyException).Entries.Single().Reload();
throw new UowUpdateConcurrencyException();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return ret;
}
出于这个问题的目的,我们假设一次只在数据库中保存一个实体
如果保存类别,没有问题。所有测试都还可以。
当我尝试保存一个人时会出现问题(以前通过相同的上下文加载)
并且存在并发冲突。
我调试那条线
(e as DbUpdateConcurrencyException).Entries.Single().Reload();
惊喜
正确抛出了异常,但是来自数据库的实体
是Category类型而不是Person类型。
此返回类别。
(e as DbUpdateConcurrencyException).Entries.ToList()[0].Entity.GetType()
如果我通过删除以下内容中的Timestamp属性来禁用类别的并发检查,
Category类一切正常
我认为Person类中定义的导航属性存在一些问题。
你怎么看?
谢谢!
更新
看来问题出在我在ComboBox和Category属性之间设置的绑定中。
如果我发表评论,一切都很好
<ComboBox ItemsSource=\"{Binding Path=CategoryList}\"
DisplayMemberPath=\"Title\"
SelectedValuePath=\"Id\"
SelectedItem=\"{Binding Path=Category,Mode=TwoWay}\" />
如果我将组合绑定到CategoryId而不是Category,问题仍然存在。
<ComboBox ItemsSource=\"{Binding Path=CategoryList}\"
DisplayMemberPath=\"Title\"
SelectedValuePath=\"Id\"
SelectedValue=\"{Binding Path=CategoryId,Mode=TwoWay}\" />
解决方法
我发现一种解决方案似乎更像一种变通办法,因此我在一两天内不接受此解决方案,希望有人能给出解释。
解决方案包括通过与用于Person和保存操作的上下文不同的上下文来加载类别列表,该类别列表是该组合的ItemsSource。
这样可以防止将类别包括在保存范围内。
最后,我们必须将绑定设置为CategoryId属性,而不是Category属性。