通过交易增加价值

时间:2019-03-28 17:44:28

标签: c# sql-server entity-framework asp.net-core transactions

我正在使用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,我需要交易。

有什么方法可以增加体重吗?

性能对我很重要。有没有比乐观并发+错误时重新加载数据更快的方法?

2 个答案:

答案 0 :(得分:1)

在此处查看这篇文章:https://www.bogotobogo.com/CSharp/csharp_multithreading3.php

如果您使用lock关键字来处理您遇到的并发问题。 在两个线程之间共享锁对象,您将确保一个在另一个线程之后执行。

答案 1 :(得分:1)

尽管您可以使用锁/信号量,但实际上在性能方面比乐观并发要差。进行先前工作的唯一方法是实质上创建一个扼流点,一次只能进行一次更新。使用乐观并发,您可以维护并行性,并且在大多数情况下,实际上不会出现任何问题。在相对罕见的情况下,存在并发冲突,最糟糕的是您可能需要从数据库中刷新并再次提交更新。除非对数据库进行严重的优化不足,否​​则这些操作都不会花费大量时间,并且总体上对性能的影响将相对最小。从理论上讲,可能需要多个循环才能最终获得更新,但实际上这几乎是不会发生的。如果系统性能足够好,那么并发冲突从一开始就很少见(只是不足以完全打折);单个请求连续多次冲突的可能性很小。