Значение приращения с транзакцией - PullRequest
0 голосов
/ 28 марта 2019

Я разрабатываю основное приложение asp.net с EF и MsSql.Я хочу увеличить какое-то поле и быть уверенным, что его значение увеличивается правильно.

Например: значение шага tread1 увеличивается с 10 на 2, поле Thread2 увеличивает то же поле на 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; }
    }

Мое приложение является многопоточным, и мне нужны транзакции.

Есть ли способ получить прирост Райта?

Для меня важна производительность.Есть ли более быстрый метод, чем оптимистичный параллелизм + перезагрузка данных при ошибке?

Ответы [ 2 ]

1 голос
/ 28 марта 2019

Хотя вы можете использовать блокировки / семафоры, на самом деле это будет хуже с точки зрения производительности, чем оптимистичный параллелизм.Единственный способ выполнить предыдущую работу - это создать точку дросселирования, при которой одновременно может выполняться только одно обновление.Используя оптимистичный параллелизм, вы можете поддерживать параллелизм, и по большей части проблем не будет.В относительно редких случаях возникает конфликт параллелизма, хуже всего то, что вам может потребоваться обновить базу данных и снова отправить обновление.Если ваша база данных не слишком оптимизирована, ни одна из этих операций не должна занимать значительное время, а общее влияние на производительность будет относительно минимальным.Хотя теоретически возможно, что для окончательного обновления потребуется несколько циклов, на практике это практически никогда не произойдет.Если система достаточно эффективна, конфликты параллелизма начинаются довольно редко (просто не достаточно редко, чтобы полностью дисконтировать);вероятность того, что один запрос попадет в конфликт несколько раз подряд, бесконечно мала.

1 голос
/ 28 марта 2019

Прочтите эту статью здесь: https://www.bogotobogo.com/CSharp/csharp_multithreading3.php

Если вы используете ключевое слово lock для решения проблемы параллелизма, которая у вас возникла.Разделите объект блокировки между двумя потоками, и вы убедитесь, что один выполняется за другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...