Хотите использовать идентификатор, возвращенный из вставки, в последующей вставке в транзакции

Я использую Massive Роба Конери для доступа к базе данных. Я хочу обернуть транзакцию вокруг пары вставок, но вторая вставка использует идентификатор, возвращенный из первой вставки. Для меня не очевидно, как это сделать в транзакции. Некоторая помощь будет оценена по достоинству.

var commandList = new List<DbCommand>
    {
        contactTbl.CreateInsertCommand(new
            {
                newContact.Name,
                newContact.Contact,
                newContact.Phone,
                newContact.ForceChargeThreshold,
                newContact.MeterReadingMethodId,
                LastModifiedBy = userId,
                LastModifiedDate = modifiedDate,
            }),
        branchContactTbl.CreateInsertCommand(new
            {
                newContact.BranchId,
                ContactId = ????, <-- how to set Id as identity from previous command
            }),
    };

person David Clarke    schedule 23.03.2011    source источник


Ответы (2)


Можете ли вы просто сделать это в хранимой процедуре? Вы можете использовать scope_identity или, что еще лучше, предложение output, чтобы получить нужные вам значения. И все вставки во все таблицы находятся в одной транзакции, которую можно откатить, если какая-то из них не сработает.

person HLGEM    schedule 26.02.2013

Сделайте запрос между этими двумя вставками, этот метод от Massive может быть полезен:

public object Scalar(string sql, params object[] args) {
    object result = null;
    using (var conn = OpenConnection()) {
        result = CreateCommand(sql, conn, args).ExecuteScalar();
    }
    return result;
} 

Ваш sql будет = "выберите scope_identity ()"

ОБНОВЛЕНИЕ 26 февраля 2013 г.

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

Приведенный выше код будет работать только тогда, когда соединение, которое делает "select scope_identity()", находится в пуле. (Это должно быть то же соединение, что и вставка).

Метод Massive table.Insert(..) возвращает Dynamic, который содержит поле ID, заполненное «SELECT @@IDENTITY». Он получает последний вставленный идентификатор из глобальной области видимости, что является очевидной ошибкой (очевидной в многопоточных сценариях).

person pkmiec    schedule 23.03.2011
comment
Спасибо, Ду, учитывая, что мне нужно ввести личность в следующую команду, это не будет соответствовать шаблону Massive. На данный момент я работаю над этим, перетаскивая код из Massive в свой класс, который далеко не идеален. - person David Clarke; 24.03.2011
comment
Вызов Scalar не вернет запрошенное значение, поскольку он откроет новое соединение (см. Massive.cs), используйте var newID = table.Insert(...), затем проверьте newId.ID, см. также stackoverflow.com/questions/15075913/ - person Ron Harlev; 26.02.2013
comment
Хм, ты прав. Я думаю, это в основном работает из-за пула соединений. Однако, глядя на массивный код, он прослушивается, @@Identity получает последний вставленный идентификатор из глобальной области, а не из текущей области соединения. - person pkmiec; 26.02.2013
comment
Имейте в виду, что вы никогда не захотите возвращать @@identity для этой цели (вы потеряете целостность данных, если кто-то поместит триггер в таблицу для вставки в другую таблицу с идентификатором), и если этот Massive сделает это, человек, который написал это, явно не компетентен в доступе к базам данных сервера sql. Если он ошибся в этом основном, то кто знает, как плохо написано остальное. - person HLGEM; 26.02.2013