c# – 事务死锁,如何设计正确?

前端之家收集整理的这篇文章主要介绍了c# – 事务死锁,如何设计正确?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以我正在研究这个实体框架项目,这个项目将被用作DAL,当运行压力测试(通过Thread()启动实体的几个更新)时,我得到这些:

_innerException = {“Transaction (Process ID 94) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.”}

以下是我如何实现我的类的方法的一些例子:

  1. public class OrderController
  2. {
  3.  
  4. public Order Select(long orderID)
  5. {
  6. using (var ctx = new BackEndEntities())
  7. {
  8.  
  9. try
  10. {
  11. var res = from n in ctx.Orders
  12. .Include("OrderedServices.Professional")
  13. .Include("Agency")
  14. .Include("Agent")
  15. where n.OrderID == orderID
  16. select n;
  17. return res.FirstOrDefault();
  18. }
  19. catch (Exception ex)
  20. {
  21. throw ex;
  22. }
  23. }
  24. }
  25.  
  26. public bool Update(Order order)
  27. {
  28. using (var ctx = new BackEndEntities())
  29. {
  30. try
  31. {
  32. order.ModificationDate = DateTime.Now;
  33. ctx.Orders.Attach(order);
  34. ctx.SaveChanges();
  35. return true;
  36. }
  37. catch (Exception ex)
  38. {
  39. throw ex;
  40. }
  41. }
  42. }
  43. }

和:

  1. public class AgentController
  2. {
  3.  
  4. public Agent Select(long agentID)
  5. {
  6. using (var ctx = new BackEndEntities())
  7. {
  8. try
  9. {
  10. var res = from n in ctx.Agents.Include("Orders")
  11. where n.AgentID == agentID
  12. select n;
  13. return res.FirstOrDefault();
  14. }
  15. catch (Exception ex)
  16. {
  17. throw ex;
  18. }
  19. }
  20.  
  21. }
  22.  
  23. public bool Update(Agent agent)
  24. {
  25. using (var ctx = new BackEndEntities())
  26. {
  27. try
  28. {
  29. agent.ModificationDate = DateTime.Now;
  30. ctx.Agents.Attach(agent);
  31. ctx.ObjectStateManager.ChangeObjectState(agent,System.Data.EntityState.Modified);
  32. ctx.SaveChanges();
  33. return true;
  34. }
  35. catch (Exception ex)
  36. {
  37. throw ex;
  38. }
  39. }
  40. }
  41. }

显然,这里的代码可能会更好,但我更喜欢EF新手.但我认为我的问题是上下文的设计问题.

我记得有人在这里提到,如果我的上下文不共享,我不会遇到这些死锁问题.

这对我来说似乎并不“共享”,因为我在每个方法中使用新的BackEndEntities(),所以我必须改变什么才能使其更加健壮?

这个DAL将用于在互联网上暴露的Web服务(在coure的代码审查之后),所以我无法控制多少会受到压力,许多不同的实例可能想要更新同一个实体.

谢谢!

解决方法

僵局自由在一个大系统中是一个非常困难的问题.它与EF本身无关.

缩短事务的使用寿命可以减少死锁,但会导致数据不一致.在你以前死锁的地方,你现在正在破坏数据(没有任何通知).

因此,根据逻辑事务选择您的上下文生命周期和事务生命周期,而不是根据物理考虑.

打开快照隔离.这需要完全超出等式的阅读交易.

对于编写交易,您需要找到锁定订单.通常情况下,最简单的方法就是将悲观情绪锁定在更高层次上.示例:您是否始终在客户的上下文中修改数据?以该客户的更新锁作为交易的第一个声明.通过序列化对该客户的访问来提供完全的死锁自由.

猜你在找的C#相关文章