我正在使用EF和MsSql开发asp.net核心应用程序。我想增加一些字段并确保其正确增加。
例如:踏步1将值从10增加2,线程2将同一字段增加1。 结果必须为 13 。但实际上我得到11,因为线程2在线程1提交之前获取数据,线程2在线程1之后提交。
示例代码:
internal class Program
{
private static void Main(string[] args)
{
try
{
using (var context = new MyContext())
{
context.Database.Migrate();
context.Books.Add(new Book {Amount = 10});
context.SaveChanges();
}
var context1 = new MyContext();
var context2 = new MyContext();
var transaction1 = context1.Database.BeginTransaction();
var transaction2 = context2.Database.BeginTransaction();
var book1 = context1.Books.Single();
var book2 = context2.Books.Single();
book1.Amount += 2;
//some other changes with entities here, so i need transactions
book2.Amount += 1;
//some other changes with entities here, so i need transactions
context1.SaveChanges();
transaction1.Commit();
context2.SaveChanges();
transaction2.Commit();
}
catch (Exception e)
{
Console.WriteLine(e);
}
var result = new MyContext().Books.Single().Amount;
Console.WriteLine($"Result: {result}");
Console.ReadLine();
}
}
public class MyContext : DbContext
{
public virtual DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=localhost\\SQLEXPRESS;Database=CashboxDomain1;Trusted_Connection=True;ConnectRetryCount=0");
}
}
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public int Amount { get; set; }
}
我的应用程序是mutltithread,我需要交易。
有什么方法可以增加体重吗?
性能对我很重要。有没有比乐观并发+错误时重新加载数据更快的方法?
答案 0 :(得分:1)
在此处查看这篇文章:https://www.bogotobogo.com/CSharp/csharp_multithreading3.php
如果您使用lock关键字来处理您遇到的并发问题。 在两个线程之间共享锁对象,您将确保一个在另一个线程之后执行。
答案 1 :(得分:1)
尽管您可以使用锁/信号量,但实际上在性能方面比乐观并发要差。进行先前工作的唯一方法是实质上创建一个扼流点,一次只能进行一次更新。使用乐观并发,您可以维护并行性,并且在大多数情况下,实际上不会出现任何问题。在相对罕见的情况下,存在并发冲突,最糟糕的是您可能需要从数据库中刷新并再次提交更新。除非对数据库进行严重的优化不足,否则这些操作都不会花费大量时间,并且总体上对性能的影响将相对最小。从理论上讲,可能需要多个循环才能最终获得更新,但实际上这几乎是不会发生的。如果系统性能足够好,那么并发冲突从一开始就很少见(只是不足以完全打折);单个请求连续多次冲突的可能性很小。