Я написал программу linq-to-sql, которая, по сути, выполняет задачу ETL, и я заметил много мест, где распараллеливание улучшит свою производительность. Однако я обеспокоен предотвращением нарушений ограничений уникальности, когда два потока выполняют следующую задачу (код psuedo).
Record CreateRecord(string recordText)
{
using (MyDataContext database = GetDatabase())
{
Record existingRecord = database.MyTable.FirstOrDefault(record.KeyPredicate());
if(existingRecord == null)
{
existingRecord = CreateRecord(recordText);
database.MyTable.InsertOnSubmit(existingRecord);
}
database.SubmitChanges();
return existingRecord;
}
}
Как правило, этот код выполняет оператор SELECT
для проверки существования записи, а затем оператор INSERT
, если запись не существует. Он заключен в неявную транзакцию.
Когда два потока запускают этот код для одного и того же экземпляра recordText
, я хочу запретить им одновременно определить, что запись не существует, тем самым оба пытаются создать одну и ту же запись. Уровень изоляции и явная транзакция будут работать хорошо, за исключением того, что я не уверен, какой уровень изоляции мне следует использовать - Serializable
должен работать, но кажется слишком строгим. Есть ли лучший выбор?