Позвольте запросу прочитать данные до того, как он будет зафиксирован - Sql Server - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть таблица с именем ProjectActivity с первичным ключом: ProjectCode и ActivityId и индекс для ProjectCode Наши веб-сайты генерируют запросы к этой таблице (без использования других таблиц) и всегда запрашивают строки с одинаковым ProjectCode

Иногда мы запускаем задание в c #, которое удаляет все строки с определенным ProjectCode и вставляет новые строки для этого конкретного ProjectCode в транзакцию.

            using (var dbContextTransaction = db.Database.BeginTransaction())
        {
            try
            {

                db.Database.ExecuteSqlCommand("delete FROM [TS_Repository].[dbo].[ProjectActivities] where ProjectCode = {0} ", project.Code);

                LogManager.WriteRequestLog("Deleted Existing Project Activities");

                if (ProjectActivities.Count > 0)
                {
                    db.Set<ProjectActivity>().AddRange(ProjectActivities);
                    db.SaveChanges();

                }

                dbContextTransaction.Commit();

                LogManager.WriteRequestLog("Refresh ProjectActivities succesfully for " + project.Title);
            }
            catch (Exception exc)
            {

                dbContextTransaction.Rollback();
                throw exc;
            }
        }

Наша проблема в том, что, хотя эта транзакция (3/4 минуты) обрабатывается, наши веб-сайты не могут выполнить какой-либо запрос (вся таблица заблокирована). Мы должны получить этот сценарий: До совершения транзакции веб-сайт должен запрашивать «старые» данные. Возможно ли реализовать этот сценарий? Я могу понять, что мы должны обмануть уровень блокировки и изоляции.

Заранее благодарю за любые советы.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

вы обратились ко мне в правильном направлении, но я думаю, мне нужен уровень изоляции SNAPSHOT, потому что я указал, что мне нужно прочитать старую версию строки.Может быть, я не так хорошо объяснил ...

Итак, я решил использовать SNASPHOT:

using (var dbContextTransaction = db.Database.BeginTransaction(System.Data.IsolationLevel.Snapshot))
        {
            try
            {


                db.Database.ExecuteSqlCommand("delete FROM [TS_Repository].[dbo].[ProjectActivities] where ProjectCode = {0} ", project.Code);

                LogManager.WriteRequestLog("Deleted Existing Project Activities");

                if (ProjectActivities.Count > 0)
                {
                    db.Set<ProjectActivity>().AddRange(ProjectActivities);
                    db.SaveChanges();

                }

                dbContextTransaction.Commit();

                LogManager.WriteRequestLog("Refresh ProjectActivities succesfully for " + project.Title);
            }
            catch (Exception exc)
            {

                dbContextTransaction.Rollback();
                throw exc;
            }
        }
0 голосов
/ 24 апреля 2018

Да, вы можете выполнять свои запросы с определенным УРОВНЕМ ИЗОЛЯЦИИ , который может читать данные, когда таблица или строка заблокированы. Я не буду вступать в дискуссию о рисках чтения незафиксированных данных, я полагаю, вы уже знаете, и @iamdave поделился хорошей ссылкой по этому поводу.

Если вы хотите прочитать незафиксированные данные, есть несколько способов сделать это с EF, но простой и понятный способ сделать это - использовать транзакцию. В конструкторе TransactionScope вы можете установить IsolationLevel, например:

using (new TransactionScope(
           TransactionScopeOption.Required, 
           new TransactionOptions 
           { 
              IsolationLevel = IsolationLevel.ReadUncommitted 
           })) 
{
        // here you put your code
}

Вот еще одно хорошее прочтение о EF и уровне изоляции: уровень сущности-каркас-и-транзакции-изоляции

...