Мы получаем очень неустойчивое (как каждые несколько недель кто-то жалуется на это) нарушение ограничения первичного ключа в нашем веб-приложении.Я искал базу кода, и единственный код, который даже создает какие-либо строки в этой таблице, выглядит следующим образом:
decimal nextDocId = (from d in context.TPM_PROJECTVERSIONDOCS
orderby d.DOCUMENTID descending
select d.DOCUMENTID).Max() + 1;
foreach (TPM_PROJECTVERSIONDOCS doc in documents)
{
TPM_PROJECTVERSIONDOCS newDoc = new TPM_PROJECTVERSIONDOCS();
newDoc.DOCUMENTID = nextDocId;
newDoc.DOCBLOB = doc.DOCBLOB;
newDoc.DOCUMENTNAME = doc.DOCUMENTNAME;
newDoc.FILECONTENTTYPE = doc.FILECONTENTTYPE;
version.TPM_PROJECTVERSIONDOCS.Add(newDoc);
nextDocId++;
}
Ошибка, которую мы получаем:
ORA-00001: unique constraint (TPMDBO.TPM_PROJECTVERSIONDOCS_PK) violated
Это означает, чточто DOCUMENTID
уже используется.У меня есть несколько теорий относительно того, что вызывает это.Во-первых, если несколько человек добавляли документы одновременно, где-то между временем, когда было установлено nextDocId
, и временем, когда был сохранен контекст, новые документы могли быть добавлены в базу данных.Однако это время будет всего несколько миллисекунд, поэтому я думаю, что это маловероятно при небольшом объеме трафика, который получает наш сайт.
Моя вторая теория, возможно, EF выполняет какое-то кэширование, а nextDocId
возвращаеткэшированное значение, которое больше не является допустимым.
Поскольку эта ошибка возникает очень часто и, конечно, только на наших производственных серверах, у меня нет хороших способов отладки или воспроизведения.
Мой вопрос: Какова наиболее вероятная причина этого, и есть ли лучший способ переписать этот код для предотвращения нарушений первичного ключа?Я бы хотел использовать только поле автоинкремента для первичного ключа, но, к сожалению, Oracle их не поддерживает.Переключение на UUID также будет решением, но приведет к большому количеству изменений в БД.Спасибо!
ОБНОВЛЕНИЕ:
Вот сущность TPM_PROJECTVERSIONDOCS
:
<EntityType Name="TPM_PROJECTVERSIONDOCS">
<Key>
<PropertyRef Name="DOCUMENTID" />
</Key>
<Property Name="DOCUMENTID" Type="decimal" Nullable="false" />
<Property Name="PROJECTID" Type="decimal" Nullable="false" />
<Property Name="VERSIONID" Type="decimal" Nullable="false" />
<Property Name="DOCUMENTNAME" Type="VARCHAR2" Nullable="false" MaxLength="500" />
<Property Name="DOCBLOB" Type="BLOB" Nullable="false" />
<Property Name="FILECONTENTTYPE" Type="VARCHAR2" Nullable="false" MaxLength="80" />
</EntityType>
Я не знаю ни одного способа сделать DOCUMENTID
по умолчанию для последовательности или для запроса последовательности, используя EF.