【发布时间】:2019-12-14 17:53:22
【问题描述】:
使用 Dapper ORM 检查记录是否存在的最简单方法是什么?
我真的需要为只想检查记录是否存在的查询定义 POCO 对象吗?
【问题讨论】:
标签: dapper
使用 Dapper ORM 检查记录是否存在的最简单方法是什么?
我真的需要为只想检查记录是否存在的查询定义 POCO 对象吗?
【问题讨论】:
标签: dapper
int id = ...
var exists = conn.ExecuteScalar<bool>("select count(1) from Table where Id=@id", new {id});
应该可以...
【讨论】:
COUNT(DISTINCT 1) 即可确保您得到 1 (true) 的答案,即使您有多个具有相同 id/key 的记录。诚然,这应该是一个极端情况。
1 被 Dapper 解析为 bool(true)?所以如果你有 2 它会失败吗?因此评论?
true。评论的原因很简单, 2 可能是一个意外的值,所以......它隐藏了一个问题。我个人更喜欢<int>
我认为这可能会减少一点开销,因为没有函数调用或数据类型转换:
int id = ...
var exists = connection.Query<object>(
"SELECT 1 WHERE EXISTS (SELECT 1 FROM MyTable WHERE ID = @id)", new { id })
.Any();
【讨论】:
const string sql = "SELECT CAST(CASE WHEN EXISTS (SELECT 1 FROM MyTable WHERE Id = @Id) THEN 1 ELSE 0 END as BIT)";
bool exists = db.ExecuteScalar<bool>(sql, new { Id = 123 });
【讨论】:
你可以让你的查询返回一个布尔值:
[Test]
public void TestExists()
{
var sql = @"with data as
(
select 1 as 'Id'
)
select CASE WHEN EXISTS (SELECT Id FROM data WHERE Id = 1)
THEN 1
ELSE 0
END AS result
from data ";
var result = _connection.Query<bool>(sql).FirstOrDefault();
Assert.That(result, Is.True);
}
【讨论】:
WHERE 子句按具有唯一索引的列过滤,优化器可以断定将有 0 或 1 行并执行查找而不是表扫描。我猜这里就是这种情况,因为列名为“id”。
conn.QuerySingleOrDefault<bool>("select top 1 1 from table where id=@id", new { id});
【讨论】:
另一个将运行重复记录的选项,即不查询表的 id
bool exists = connection.ExecuteScalar<int>(
"select count(1) from Table where notanId=@value", new { value = val})
> 0;
【讨论】:
如果您需要对非唯一字段执行此类查询,您可以使用HAVING 处理大于 1 的计数。
SELECT 1
FROM Table
WHERE Col=@val
HAVING COUNT(1) > 0
【讨论】:
恕我直言SELECT TOP(1)比SELECT COUNT(1)好
bool exists = connection.Query<ValueTuple<long>>(
"SELECT top(1) Id FROM MYTABLE WHERE MYTABLE.Id=@Id",
new {Id}).Any());
ValueTuple<long> 是值类型。 Query<object> 映射到引用类型并导致装箱。
【讨论】: