2009-12-09 4 views
3

есть способ узнать идентификатор столбца идентификации записи, вставленный через InsertOnSubmit заранее, например. перед вызовом datasource SubmitChanges?Ссылка на идентификатор объекта перед отправкой изменений в LINQ

Предположим, что я заполняю какую-то иерархию в базе данных, но я бы не хотел отправлять изменения для каждого рекурсивного вызова каждого дочернего узла (например, если бы у меня была таблица каталогов и таблица файлов и я воссоздал структуру своей файловой системы в базе данных).

Я хотел бы сделать это таким образом, чтобы я создать объект каталога, установить его имя и атрибуты, затем InsertOnSubmit его в коллекцию DataContext.Directories, затем ссылка Directory.ID в его дочерних файлов. В настоящее время мне нужно вызвать InsertOnSubmit, чтобы вставить «каталог» в базу данных, а сопоставление базы данных заполняет его столбец идентификаторов. Но это создает много транзакций и доступа к базе данных, и я полагаю, что если бы я это вставлял в пакет, производительность была бы лучше.

Что бы я хотел сделать, так это использовать Directory.ID перед тем, как совершать изменения, заранее создать все мои объекты File и Directory, а затем сделать большой файл submit, который помещает все данные в базу данных. Я также открыт для решения этой проблемы с помощью хранимой процедуры, я предполагаю, что производительность будет еще лучше, если все операции будут выполняться непосредственно в базе данных.

ответ

3

Один из способов обойти это - не использовать столбец идентификации. Вместо этого создайте IdService, который вы можете использовать в коде для получения нового идентификатора каждый раз, когда создается объект Directory.

Вы можете реализовать IdService, имея таблицу, в которой хранится последний используемый идентификатор. Когда служба запустится, возьмите это число. Затем служба может увеличиваться, пока создаются объекты Directory, а затем обновляет таблицу с новым последним идентификатором, используемым в конце прогона. В качестве альтернативы, и немного безопаснее, когда служба запускается, она захватывает последний использованный идентификатор, а затем обновляет последний идентификатор, используемый в таблице, добавив 1000 (например). Затем пусть он увеличивается. Если он использует 1000 идентификаторов, попробуйте захватить следующую 1000 и обновить последнюю используемую таблицу. В худшем случае вы теряете некоторые идентификаторы, но если вы используете bigint, вам никогда не придется заботиться.

Поскольку идентификатор каталога теперь управляется кодом, вы можете использовать его с дочерними объектами, такими как Файлы, перед записью в базу данных.

Простое размещение блокировки вокруг получения идентификатора делает это безопасным для использования в нескольких потоках. Я использовал это в такой ситуации, как ваша. Мы генерируем массу объектов в памяти по нескольким потокам и сохраняем их в пакетах.

This blog post даст вам хорошее начало для сохранения пакетов в Linq to SQL.

1

Не уверен сверху, если есть способ запустить прямой SQL-запрос в LINQ, но этот запрос вернет текущее значение идентификатора указанной таблицы.

USE [database]; 
GO 
DBCC CHECKIDENT ("schema.table", NORESEED); 
GO 
+0

спасибо, но я могу сгенерировать тысячи записей в одной партии и даже на несколько разных потоков, поэтому значения столбцов идентификатора будут смешиваться. Я думал об отключении автоматической генерации идентификаторов, но потом понял, что могу запустить сразу несколько таких запросов, и я не смог бы достоверно генерировать значения идентификаторов самостоятельно. – Axarydax

+0

Да, я сначала вас не понял. Я думал, что вы просто говорите об одном объекте каталога за раз со многими файлами, но на самом деле вам нужно много каталогов и много файлов за раз. – ryanulit

Смежные вопросы