У меня серьезная проблема с производительностью LINQ2SQL и транзакциями. Мой код выполняет следующие действия, используя сгенерированный IDE код LINQ2SQL:
Запустить проверку сохраненной процедуры для существующей записи
Создать запись, если она не существует
Запустите сохраненный процесс, который оборачивает свой собственный код в транзакцию
Когда я запускаю код без области транзакции, я получаю 20 итераций в секунду. Как только я заключаю код в область транзакции, он падает до 3-4 итераций в секунду. Я не понимаю, почему добавление транзакции на верхнем уровне значительно снижает производительность. Пожалуйста, помогите?
Псевдо сохраненный процесс с транзакцией:
begin transaction
update some_table_1;
insert into some_table_2;
commit transaction;
select some, return, values
Псевдо-код LINQ без транзакции:
var db = new SomeDbContext();
var exists = db.RecordExists(some arguments);
if (!exists) {
var record = new SomeRecord
{
// Assign property values
};
db.RecordsTable.InsertOnSubmit(record);
db.SubmitChanges();
var result = db.SomeStoredProcWithTransactions();
}
Псевдо-LINQ код с транзакцией:
var db = new SomeDbContext();
var exists = db.RecordExists(some arguments);
if (!exists) {
using (var ts = new TransactionScope())
{
var record = new SomeRecord
{
// Assign property values
};
db.RecordsTable.InsertOnSubmit(record);
db.SubmitChanges();
var result = db.SomeStoredProcWithTransactions();
ts.Complete();
}
}
Я знаю, что транзакция не передается в DTC, потому что я отключил DTC. SQL Profiler показывает, что некоторые запросы выполняются гораздо дольше при включенной транзакции, но я не уверен, почему. Запросы выполняются очень недолго, и у меня есть индексы, которые, как я проверял, используются. Я не могу определить, почему добавление родительской транзакции приводит к такому снижению производительности.
Есть идеи?
EDIT:
Я проследил проблему до следующего запроса в последней хранимой процедуре:
if exists
(
select * from entries where
ProfileID = @ProfileID and
Created >= @PeriodStart and
Created < @PeriodEnd
) set @Exists = 1;
Если бы я использовал (nolock), как показано ниже, проблема исчезнет.
if exists
(
select * from entries with(nolock) where
ProfileID = @ProfileID and
Created >= @PeriodStart and
Created < @PeriodEnd
) set @Exists = 1;
Однако я обеспокоен тем, что это может вызвать проблемы в будущем. Любой совет?