Во-первых, вы можете позвонить DB.SubmitChanges()
сразу после stats.Visits++
, и это значительно уменьшит проблему.
Однако это все равно не спасет вас от нарушения параллелизма (то есть одновременного изменения фрагмента данных двумя одновременными процессами). Чтобы бороться с этим, вы можете использовать стандартный механизм транзакций . С LINQ-to-SQL вы используете транзакции, создавая экземпляр класса TransactionScope
, таким образом:
using( TransactionScope t = new TransactionScope() )
{
var stats = DB.Stats.First();
stats.Visits++;
DB.SubmitChanges();
}
Обновление : , как правильно заметил Аарона, TransactionScope здесь не поможет. Сожалею. Но читайте дальше.
Будьте осторожны, чтобы не сделать тело транзакции слишком длинным, так как это заблокирует другие параллельные процессы и, таким образом, значительно снизит вашу общую производительность.
И это подводит меня к следующему пункту: ваш дизайн, вероятно, имеет недостатки.
Основной принцип работы с данными с высокой степенью общего доступа состоит в том, чтобы спроектировать ваше приложение таким образом, чтобы операции с этими данными были быстрыми, простыми и семантически понятными и выполнялись одна за другой, а не одновременно.
Одна операция, которую вы описываете - подсчет посещений - довольно понятна и проста, поэтому не должно возникнуть никаких проблем после добавления транзакции. Однако я должен добавить, что, хотя это будет понятно, безопасно для типов и в остальном «хорошо», решение с хранимой процедурой на самом деле является гораздо более предпочтительным. Это на самом деле именно так, как приложения баз данных были разработаны в прежние времена. Подумайте об этом: зачем вам нужно извлекать счетчик на всем пути от базы данных до вашего приложения (возможно, по сети!), Если в его обработке не задействована бизнес-логика. Сервер базы данных может также увеличивать его, даже не отправляя ничего обратно приложению.
Теперь, что касается других операций, которые скрыты за // ...
, кажется (по вашему описанию), что они несколько тяжелые и длинные. Я не могу сказать наверняка, потому что я не вижу, что там, но если это так, вы, вероятно, хотите разделить их на более мелкие и более быстрые, или иначе переосмыслить свой дизайн. Я действительно не могу ничего сказать с этой маленькой информацией.