У меня есть таблица с именем People со следующей схемой:
Id INT NOT NULL IDENTITY(1, 1)
FirstName NVARCHAR(64) NOT NULL
LastName NVARCHAR964) NOT NULL
Я использую запрос, подобный этому, для выполнения вставок и обновлений в одном запросе:
MERGE INTO People AS TARGET
USING ( VALUES
(@id0, @firstName0, @lastname0),
(@id1, @firstName1, @lastname1)
...
) AS SOURCE ([Id],[FirstName],[LastName])
ON TARGET.[Id] = SOURCE.[Id]
WHEN MATCHED BY TARGET THEN
UPDATE SET
[FirstName] = SOURCE.[FirstName],
[LastName] = SOURCE.[LastName]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([FirstName],[LastName])
VALUES ([FirstName],[LastName])
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT $action, INSERTED.*;
MyПриложение структурировано так, что клиент перезванивает на сервер для загрузки существующего состояния приложения.Затем клиент создает / изменяет / удаляет объекты локально и передает эти изменения на сервер в виде одной связки.
Вот пример того, как мой код "SaveEntities" в настоящее время выглядит:
public void SavePeople(IEnumerable<Person> people)
{
// Returns the query I mentioned above
var query = GetMergeStatement(people);
using(var command = new SqlCommand(query))
{
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
// how do I tie these records back to
// the objects in the people collection?
}
}
}
}
Я могу использовать значение в столбце $action
, чтобы отфильтровать до просто ВСТАВЛЕННЫХ записей.INSERTED.*
возвращает все столбцы в TARGET для вставленной записи.Проблема в том, что у меня нет способа четко связать эти результаты с набором объектов, переданных в этот метод.
Единственное решение, о котором я мог подумать, - это добавить в таблицу столбец GUID с возможностью записи и разрешить MERGE.оператор, чтобы указать это значение, чтобы я мог ссылаться на эти объекты в коде, используя его, и назначить оттуда значение идентификатора, но кажется, что это противоречит цели иметь столбец автоматической идентификации и выглядит запутанным.
IМне действительно любопытно, как это может работать, потому что я знаю, что Entity Framework делает что-то, чтобы смягчить эту проблему (чтобы было ясно, я думаю, что мне пришлось бы столкнуться с той же проблемой, если бы я использовал чистый оператор INSERT вместо MERGE).В EF я могу добавлять объекты в модель, вызывать Entity.SaveChanges()
и автоматически обновлять свойство идентификатора объекта, используя магию.Я думаю, что это та магия, которую я хочу понять больше.
Кроме того, я знаю, что я мог бы структурировать свои сохранения таким образом, чтобы вставлять по одной записи за раз и каскадно вносить изменения (возвращая SCOPE_IDENTITY
для каждоговставить), но это было бы ужасно неэффективно.