【问题标题】:Check if record exists with Dapper ORM使用 Dapper ORM 检查记录是否存在
【发布时间】:2019-12-14 17:53:22
【问题描述】:

使用 Dapper ORM 检查记录是否存在的最简单方法是什么?

我真的需要为只想检查记录是否存在的查询定义 POCO 对象吗?

【问题讨论】:

    标签: dapper


    【解决方案1】:
    int id = ...
    var exists = conn.ExecuteScalar<bool>("select count(1) from Table where Id=@id", new {id});
    

    应该可以...

    【讨论】:

    • @webworm 请注意,如果您有超过 1 条记录与密钥,它会变得很棘手,但是......你不应该有 :)
    • 只需使用 COUNT(DISTINCT 1) 即可确保您得到 1 (true) 的答案,即使您有多个具有相同 id/key 的记录。诚然,这应该是一个极端情况。
    • 我猜这是因为 1 被 Dapper 解析为 bool(true)?所以如果你有 2 它会失败吗?因此评论?
    • @Liam 我希望 2 将评估为true。评论的原因很简单, 2 可能是一个意外的值,所以......它隐藏了一个问题。我个人更喜欢&lt;int&gt;
    【解决方案2】:

    我认为这可能会减少一点开销,因为没有函数调用或数据类型转换:

    int id = ...
    var exists = connection.Query<object>(
        "SELECT 1 WHERE EXISTS (SELECT 1 FROM MyTable WHERE ID = @id)", new { id })
        .Any();
    

    【讨论】:

      【解决方案3】:
      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 });
      

      【讨论】:

      • 我喜欢这个答案,因为 SQL 表达了意图并且您不依赖类型转换。
      • 这应该被标记为正确答案
      【解决方案4】:

      你可以让你的查询返回一个布尔值:

          [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);
          }
      

      【讨论】:

      • 不,不同意。 'Count' 处理整个表,因为查询优化器无法排除 where 子句的多个匹配项。一旦找到第一个匹配项,'Exists' 就会返回。当表中有很多行时,差异可能会很大,尤其是在经常重复此查询的情况下。例如,请参阅我发现的这篇博文 - sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/…
      • @Volkirith 一般来说,这是真的,但有一个例外。如果WHERE 子句按具有唯一索引的列过滤,优化器可以断定将有 0 或 1 行并执行查找而不是表扫描。我猜这里就是这种情况,因为列名为“id”。
      【解决方案5】:
      conn.QuerySingleOrDefault<bool>("select top 1 1 from table where id=@id", new { id});
      

      【讨论】:

        【解决方案6】:

        另一个将运行重复记录的选项,即不查询表的 id

        bool exists = connection.ExecuteScalar<int>(
            "select count(1) from Table where notanId=@value", new { value = val})
             > 0;
        

        【讨论】:

          【解决方案7】:

          如果您需要对非唯一字段执行此类查询,您可以使用HAVING 处理大于 1 的计数。

          SELECT 1
          FROM Table
          WHERE Col=@val
          HAVING COUNT(1) > 0
          

          【讨论】:

            【解决方案8】:

            恕我直言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&lt;long&gt; 是值类型。 Query&lt;object&gt; 映射到引用类型并导致装箱。

            【讨论】:

              猜你喜欢
              • 2012-07-08
              • 1970-01-01
              • 2021-02-21
              • 2011-02-20
              • 2015-01-21
              • 2012-08-13
              • 2015-01-02
              相关资源
              最近更新 更多