【发布时间】:2016-10-05 22:38:05
【问题描述】:
我有一个 SQL Server 表,其中插入了行:
var sql = @"
DECLARE @InsertedRows AS TABLE (Id BIGINT);
INSERT INTO Person ([Name], [Age]) OUTPUT Inserted.Id INTO @InsertedRows
VALUES (@Name, @Age);
SELECT Id FROM @InsertedRows;";
Person person = ...;
var id = connection.Query<long>(sql, person).First();
这一切都很好,但是如果我尝试插入多个项目并使用以下方法返回所有插入的 id:
IEnumerable<Person> people = ...;
var ids = connection.Query<long>(sql, people);
我收到一个错误:
System.InvalidOperationException : 在此上下文中不允许使用可枚举的参数序列(数组、列表等)
在 Dapper.SqlMapper.GetCacheInfo(Identity identity, Object exampleParameters, Boolean addToCache)
在 Dapper.SqlMapper.d__23`1.MoveNext()
--- 从之前抛出异常的位置结束堆栈跟踪 ---
如何在 Dapper 中返回多个插入的 id?
【问题讨论】:
-
Query<T>确实返回IEnumerable<T>,因此在第一个查询中使用First()。 -
问题不在于 Dapper 是否支持返回多个行 ID,而实际上是“插入后如何获取多个行 ID?”。它只是执行你给它的 SQL。您希望
INSERTSQL 执行多次(取决于people),但最终选择执行一次。这将要求 Dapper 了解您正在执行的 SQL,但它没有。想想如果没有 Dapper(只是在普通 SQL 中)你将如何做到这一点,你会发现你正在尝试做的事情并不完全有意义——你需要多个插入语句 -
实际上这不是真的,dapper 知道如何将 IEnumerable
映射到转义的 SQL,因此将其与使用普通 SQL 执行此操作的方式进行比较是无关紧要的。您可以自己尝试一下,将 sql替换为:INSERT INTO Person ([Name], [Age]) VALUES (@Name, @Age);并用SqlMapper.Execute()执行它,您将看到正确插入的所有项目。 -
@Rob,我明白你现在的意思了。嗯...我希望它以以下方式运行查询:
DECLARE @InsertedRows AS TABLE (Id BIGINT); INSERT INTO Person ([Name], [Age]) OUTPUT Inserted.Id INTO @InsertedRows VALUES (@Name1, @Age1),(@Name2, @Age2),...; SELECT Id FROM @InsertedRows;";确实可以使用纯 SQL。在那种情况下,如何在 Dapper 中实现相同的目标? -
@MaYaN 我相信最好的方法是进行单独的查询: 1. 创建一个临时表(而不仅仅是一个变量)。以
Execute而不是Query的身份运行插入,并输出到临时表中。对临时表运行Query,然后删除临时表。对我来说,这似乎并不理想,但我正在努力寻找更好的方法。
标签: c# .net sql-server dapper