EF LINQ запросы только SELECT.Единственное, что вы можете сделать без любого SQL, - это запускать запросы, сохранять изменения в сущностях и выполнять транзакции.И нет никакого способа сделать то, что вы хотите (по крайней мере, в SQL Server) без предложения OUTPUT или подсказок блокировки.
Это распространенное заблуждение, что транзакция, использующая уровень изоляции SERIALIZABLE , будет работать здесь,Но это не так.Когда вы читаете в транзакции SERIALIZABLE, вы помещаете общие (S) блокировки в строки (и диапазоны), удовлетворяющие предикатам запроса, и удерживаете эти блокировки в течение всей транзакции.Поскольку это общие блокировки, две SERIALIZABLE транзакции могут читать одну и ту же строку.Затем, если любая из транзакций попытается преобразовать общую блокировку в эксклюзивную блокировку для обновления строки, она будет заблокирована другой транзакцией.Если оба пытаются обновить, возникает тупик.
Таким образом, вы могли бы поместить код в цикл, перехватывая и повторяя попытки при взаимных блокировках, но это не очень рекомендуется в высокочастотной транзакции, и тупик обрекает всю вашу транзакцию, поэтомуцикл может потребоваться повторить много других операторов.Значительно хуже, чем шаблон UPDATE… OUTPUT, используемый здесь.
Конечно, шаблон намного лучше - вместо этого использовать несколько объектов SEQUENCE .Потому что даже с UPDATE ... OUTPUT только одна транзакция может генерировать значение за раз, а другие сеансы будут ждать, пока эта транзакция не завершится, пока они не смогут сгенерировать значение.С помощью ПОСЛЕДОВАТЕЛЬНОСТИ генерация не транзакционная, и несколько сеансов могут генерировать значения, не блокируя транзакции друг друга.
Здесь лучшее, что вы можете сделать, - это обернуть эту логику в хранимую процедуру и затем вызвать ее из функциина вашем DbContext.