我最近一直在使用 dapper ,除了使用表变量外,所有这些都没有问题。
为了演示,我使用this thread中的修改示例。
此代码可以正常运行:
int tally = connection.Execute(
"create table #t(Name nvarchar(max), Age int)\n" +
"insert #t (Name,Age) values(@Name, @Age)", new[]
{
new {Age = 1, Name = "sam"},
new {Age = 2, Name = "bob"}
});
但这不是:
int tally = connection.Execute(
"create table @t(Name nvarchar(max), Age int)\n" +
"insert @t (Name,Age) values(@Name, @Age)", new[]
{
new {Age = 1, Name = "sam"},
new {Age = 2, Name = "bob"}
});
唯一的变化是使用表变量而不是临时表(@ instead #
)。
Dapper(或链中的任何其他东西?)似乎以某种方式将它与参数混合并返回“必须声明表变量@t
”。
我的使用方法有什么问题,或者这是短小精悍的错误/缺失功能?
祝你好运, KC
的更新:
只是为了澄清:@t
不是dapper设置的参数。 @t
被声明为本地表,该表仅存在于当前运行的查询中。在我看来,dapper不应该区分任何类型的表,无论是“普通”表,本地/全局临时表还是表变量。
更多背景信息:
我真正想做的是:
我的目的是在从带有WHERE IN(...)子句的表中选择
时解决性能问题答案 0 :(得分:4)
如果您使用的是SQL Server,则语法不正确。在SQL Server中,表变量的创建方式与常规表的创建方式不同。它应该是这样的:
DECLARE @t TABLE (
-- table definition
);
答案 1 :(得分:1)
你错了。 Dapper和所有其他micro-Orms不关心任何sql风格所定义的表变量,它们只关心sql参数。
你应该这样做(假设表名不是来自用户输入 - 为什么要这样?!)
var tableName='my_table' ;
int tally = connection.Execute(
string.format("create table {0}(Name nvarchar(max), Age int)\n" +
"insert {0} (Name,Age) values(@Name, @Age)",tableName), new[]
{
new {Age = 1, Name = "sam"},
new {Age = 2, Name = "bob"}
});
答案 2 :(得分:0)
你说:
我的目的是在从我的选择中击败性能问题 具有WHERE IN(...)子句的表
我也担心表现。我有一个巨大的表,每次查询时都需要选择一小部分。
对我来说似乎有用的是在C#中创建DataTable
并将其传递给Dapper的AsTableValuedParameter
方法。然后我会:
将此表连接到我的一个持久表并返回 结果
如,
首先在我的数据库中创建了一个UDTT:
CREATE TYPE [dbo].[IDs] AS TABLE(
[ID] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)
然后在我的代码中创建一个DataTable:
var dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(long)));
//i'm adding from a list passed as parameter; your example is via collection initializer
foreach (var id in Ids)
{
dt.Rows.Add(id);
}
然后编写一个将大表连接到我的子集的查询:
using (IDbConnection sqlConnection = new SqlConnection(connectionString))
{
const string query = @"
SELECT *
FROM [dbo].[Candidate] c
JOIN @tvp t ON c.CandidateID = t.ID
";
var candList = sqlConnection.Query<Candidate>(query, new { tvp = dt.AsTableValuedParameter("[dbo].[IDs]") }).ToList();
return candList;
}