【问题标题】:Modifying Entity Framework Entities from Multiple Threads从多个线程修改实体框架实体
【发布时间】:2015-06-04 10:19:39
【问题描述】:

我有一个 UI 线程,它使用户能够设置实体的某些属性。

我还有工作线程,它们会自动修改实体的属性,重要的是,用户无权访问。

每个线程有不同的DbContexts 是否安全,并且仅依赖于我的编程来始终避免修改相同的属性,然后尝试在以不同方式修改相同实体的上下文中尝试SaveChanges()?

或者有没有一种更安全的方法来做到这一点,即程序员有可能在某一天更改代码,以便从两个不同的上下文安全地修改相同的属性?还是后一种情况只是程序员必须小心/重构的一种情况?

【问题讨论】:

  • 您是否关心 EF 数据结构周围的线程安全,或者您是否关心如何使对一个上下文的写入传播到其他上下文?
  • @usr 这是关于我希望能够从 UI 线程修改的实体的线程安全性和数据完整性,而长时间运行的任务会确定该实体的其他属性的值。

标签: c# multithreading entity-framework concurrency database-concurrency


【解决方案1】:

理论部分

多线程环境中有three ways to resolve the concurrency issues:

  • 悲观,对于正在编辑的项目,这可以通过locks 轻松完成 - 没有其他人可以编辑已经在编辑的项目。这是一种很难实现的方法,而且从性能的角度来看,这种方法也很糟糕——所有的编辑线程都在等待一个编写器,只是在浪费系统资源。
  • 乐观,这是解决问题的默认方式。主要思想是继续操作,直到成功为止。已经介绍了很多算法,我鼓励您阅读整个 wiki 文章,可能还有一些 additional references 和/或主题书籍。
  • 半乐观,这是一种混合方法,如果您需要lock 一些操作,但不是全部,则使用这种方法。

练习部分

实体框架作者鼓励您在应用中使用乐观的方式。 The simple use-case 是将RowVersion 或类似名称的属性添加到您的模型中,并在UPDATE 期间捕获DBUpdatedException。

您可以使用Code-First 解决方案,如下所示:

[Timestamp]
public byte[] RowVersion { get; set; }

或Database-First 解决方案(使用数据库编辑器添加列):

之后,您的简单案例代码将如下所示:

using (var context = new SchoolDBEntities())
{
    try
    {
        context.Entry(student1WithUser2).State = EntityState.Modified;
        context.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Console.WriteLine("Optimistic Concurrency exception occured");
    }
}

据我了解,您必须检查数据源的一些属性,因此我建议您阅读a great article regarding such use-cases(它是关于 MVC 应用程序,但我相信您可以掌握主要思想) .

您还可以在 MSDN 上找到几篇关于 Entity Framework 中的并发的文章:

  • Optimistic Concurrency Patterns
    • 使用 Reload 解决乐观并发异常(数据库获胜)
    • 在客户端获胜时解决乐观并发异常
    • 乐观并发异常的自定义解决方案
    • 使用对象自定义解决乐观并发异常
  • Working with Property Values
    • 获取和设置单个属性的当前值或原始值
    • 获取和设置未映射属性的当前值
    • 检查属性是否标记为已修改
    • 将属性标记为已修改
    • 读取实体所有属性的当前值、原始值和数据库值
    • 从另一个对象设置当前值或原始值
    • 从字典中设置当前值或原始值
    • 使用属性从字典中设置当前值或原始值
    • 创建包含当前值、原始值或数据库值的克隆对象
    • 获取和设置复杂属性的当前值或原始值
    • 使用DbPropertyValues 访问复杂属性

如您所见,这种情况完全依赖于开发人员,您可以选择大量模式来自行解决并发问题。

【讨论】:

    猜你喜欢
    • 2012-08-18
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多