【问题标题】:Entity Framework Operations to SQL - Prevent DeadlocksSQL 的实体框架操作 - 防止死锁
【发布时间】:2010-12-11 00:11:28
【问题描述】:

我在 SQL Server 中有一个类似于以下内容的表:

Col1  Id  -Int and Key    
Col2  ProductId  int    
Col3  ProductDesc   Varchar

在我的 Silverlight 应用程序中,我有两个网格显示该表中的数据 - 由 ProductId 分隔 - 换句话说,我将所有产品 A 放在一个网格中,将所有产品 B 放在另一个网格中。

当我选择任一网格中的任何项目时,我会将其写到表格中。如果我从网格中取消选择一个项目,我会从表格中删除该行。由于 Silverlight 使用异步调用,当一个网格忙时,用户仍然可以使用另一个网格(这是我想要的)。但是,如果用户在从另一个网格插入项目时取消选择一个网格中的项目,则会出现死锁错误。

我的所有插入都在每个实体更新后完成,并且我调用了 SubmitChanges()。正在以不同的方式处理删除。由于 EF 中没有 DeleteAll,我使用对象上下文的 ExecuteStoreCommand() 并提交 DELETE 查询 - 这可能是我的问题来自。

如何使用同一张表来完成此操作而不会出现死锁错误?我真的想避免为每个网格创建一个单独的表。

如果我使用 EF 从我的实体中删除而不是 ExecuteStoreCommand() 会更好地处理死锁吗?将表加载到内存中似乎是一种资源腰围,一次删除每一行。

编辑:我想补充一点,当我从 talbe 中删除同时 EF 插入其中时,我验证了我的死锁。

谢谢,

-斯科特

【问题讨论】:

    标签: sql-server entity-framework deadlock


    【解决方案1】:

    尝试为您的事务使用隔离级别:

    using (TransactionScope scope = 
              new TransactionScope(TransactionScopeOption.RequiresNew, 
                 new TransactionOptions() 
                 {
                    IsolationLevel = IsolationLevel.ReadUncommitted 
                 }))
    {
       // read only work - no locks on records. effectively SELECT xx from xxx WITH (NOLOCK)
    }
    

    但是,AFAIK 这是用于确定 EF 上下文查询的范围。如果您使用ExecuteStoreCommand,那么您可能必须手动将 NOLOCK 提示放在查询本身上。

    【讨论】:

    • 这应该用于我的删除还是我的插入?还是两者兼而有之?
    • 两者都不是。这应该用于只读查询 (SELECT)。插入和删除应该有独占锁。
    • 在 SQL Server Management Studio 中(如果您有访问权限),您可以监控查询并查看导致死锁的查询。
    • 明白了。再问一个问题:是否应该在创建域上下文时在客户端定义范围,还是应该在服务器上的域服务中使用它?
    • 老实说,我对 Silverlight 应用程序的工作并不多。我想这取决于您是否将数据访问逻辑封装在存储库后面。通常你会新建上下文(或使用using)语句,并在这里定义事务范围。
    【解决方案2】:

    您的删除语句是否与其他操作涉及相同的行?

    如果没有,请尝试添加行锁提示:delete from xyz with (rowlock) where ...

    【讨论】:

    • 不,我确信被删除和插入的行永远不会相同。我会试一试。那是我以前没用过的。
    • 我希望这样做可以解决问题,但不幸的是我仍然遇到了死锁。我开始怀疑插入是否是现在的问题。我不知道插入表时放置了什么隔离级别或锁。
    • 您可以尝试为表上的索引设置allow_row_locks 和allow_page_locks 选项以避免页面锁定。例如:alter index pk_some_table on some_table rebuild with (allow_row_locks=on, allow_page_locks=off)
    • 哦,您也可以使用我的实体框架分析器试一试 - 它可能会捕获有关导致死锁的更多详细信息...请参阅huagati.blogspot.com/2010/06/…
    【解决方案3】:

    以下对我有用。

    using (var context = new XXX())   // Replace XXX with your specifics
    {
      context.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;"); 
      // your LINQ code here
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多