【问题标题】:C# program not getting results from SQL queryC# 程序未从 SQL 查询中获取结果
【发布时间】:2014-10-22 10:25:36
【问题描述】:

我用 C# 编写了一个函数来从 TSQL 查询中检索结果。

public List<string> ExecuteRule(string rule)
{
    List<string> foundLCNs = new List<string>();
    try
    {
        myConnection = new SqlConnection(ConnectionString);

        SqlDataReader myReader = null;
        SqlCommand myCommand = new SqlCommand
        (
            rule, 
            myConnection 
        ); 
        myConnection.Open();

        myReader = myCommand.ExecuteReader();
        while(myReader.Read())
        {
            foundLCNs.Add(myReader["labno"].ToString());
        }
    }
    catch (Exception e)
    {
        Controller.PrintStackTrace (e);
        Console.WriteLine(e.ToString());
    }
    finally
    {
        myConnection.Close();
    }
    return foundLCNs;
}

我发现当我运行一些 SQL 查询时,没有返回任何结果,但是,当我复制 SQL 并在 Microsoft SQL Server 管理 sudio 中运行它时,我得到了一些结果。

也许查询花费的时间太长,但我没有抛出任何异常。

当我使用调试器单步执行代码时 我打到了这条线

myReader = myCommand.ExecuteReader();

执行速度很快(检索数据需要几秒钟)。

while 循环从不执行里面的代码,它只是跳过,因为没有返回数据。

编辑

SQL 看起来像这样

WITH FilterPatches AS
(
    SELECT 
        OIL_SAMPLE.labno 
    FROM OIL_SAMPLE 
    INNER JOIN LU_OIL_TEST_TYPE ON OIL_SAMPLE.test_type_auto = LU_OIL_TEST_TYPE.test_type_auto 
    LEFT JOIN OIL_EQ_UNIT ON OIL_SAMPLE.equnit_auto = OIL_EQ_UNIT.equnit_auto 
    LEFT JOIN Equipment ON OIL_EQ_UNIT.equipmentid_auto = Equipment.equipmentid_auto 
    LEFT JOIN CRSF ON Equipment.crsf_auto = CRSF.crsf_auto 
    LEFT JOIN CUSTOMER ON CRSF.customer_auto = CUSTOMER.customer_auto 
    LEFT JOIN OIL_SAMPLE_READING_STORE AS DEP ON OIL_SAMPLE.labno = DEP.labno 
    LEFT JOIN OIL_SAMPLE_READING AS DEP2 ON OIL_SAMPLE.labno_auto = DEP2.labno_auto 
    WHERE CUSTOMER.custid IN 
    ( 
        '555555', '555'
    ) AND 
    ( 
        (
            DEP.element_auto IN 
            ( 
                 SELECT element_auto 
                 FROM LU_OIL_ELEMENT 
                 WHERE LU_OIL_ELEMENT.elementid = 'DEP' 
            ) 
            AND 
            DEP.reading NOT IN ('vw', 'ok') 
        ) 
        OR 
        ( 
            DEP2.element_auto IN 
            ( 
                SELECT element_auto 
                FROM LU_OIL_ELEMENT 
                WHERE LU_OIL_ELEMENT.elementid = 'DEP' 
            ) 
            AND 
            DEP2.reading NOT IN ('vw', 'ok') 
            AND OIL_SAMPLE.data_released_date IS NULL
        )
    ) 
    AND OIL_SAMPLE.labno NOT IN
    ( 
        SELECT labno 
        FROM OIL_SAMPLE_READING_STORE 
        WHERE element_auto IN 
        ( 
            SELECT element_auto 
            FROM LU_OIL_ELEMENT 
            WHERE LU_OIL_ELEMENT.elementid = 'FPATCH' 
        ) 
    ) 
    AND LU_OIL_TEST_TYPE.test_type_desc NOT IN 
    (
        'Diesel',
        'DieselStd',
        'DieselSml'
    )
),
ParticleCountElements AS
(
    SELECT element_auto 
    FROM LU_OIL_ELEMENT 
    WHERE LU_OIL_ELEMENT.elementid IN
    (
        'AB',
        'CD'
    ) 
)
(

    SELECT labno
    FROM FilterPatches

    EXCEPT

    (
        SELECT DISTINCT labno
        FROM OIL_SAMPLE_READING_STORE
        WHERE element_auto IN
        (
            SELECT element_auto
            FROM ParticleCountElements
        )
        AND labno IN 
        (
            SELECT labno
            FROM FilterPatches
        )
        AND reading_raw IS NOT NULL

        UNION

        SELECT labno
        FROM OIL_SAMPLE 
        LEFT JOIN OIL_SAMPLE_READING ON OIL_SAMPLE.labno_auto = OIL_SAMPLE_READING.labno_auto 
        WHERE OIL_SAMPLE.data_released_date IS NULL
        AND OIL_SAMPLE_READING.element_auto IN
        (
            SELECT element_auto
            FROM ParticleCountElements
        )
        AND labno IN 
        (
            SELECT labno
            FROM FilterPatches
        )

    )
)

我已经尝试在 microsoft sql server management studio 中运行它,它运行良好。

编辑

按照建议,我已尝试将代码更改为

List<string> foundLCNs = new List<string>();

using (var cnx = new SqlConnection (ConnectionString)) 
{
    using (SqlCommand cmd = new SqlCommand (rule, cnx)) 
    {
        cmd.CommandType = CommandType.Text;
        cnx.Open ();

        using (var dr = cmd.ExecuteReader())
        {
            if (dr.HasRows) 
            {
                while (dr.Read ()) 
                {
                    if (!dr.IsDBNull (0)) 
                    {
                        foundLCNs.Add (dr.GetString (0));
                    }
                }
            }
        }
    }
}

return foundLCNs;

HasRows 博士 是假的

我仍然得到相同的行为。它适用于其他查询,但不适用于我发布的查询。但是,此查询在 SQL Server 中运行时确实有效。

【问题讨论】:

  • 你检查过执行代码的账号是否有权限查询数据库吗?
  • 尝试将 CommandType 设置为 CommandType.Text
  • 您的查询是什么样的?
  • @DeanOC 好想检查一下,但是 C# 函数可以很好地与其他 SQL 查询配合使用,因此它具有访问权限。

标签: c# sql-server tsql


【解决方案1】:

你的代码应该是这样的。

public IList<string> ExecuteRule(string rule) {
    var found = new List<string>();

    using (var cnx = new SqlConnection(connectionString)) 
        using (var cmd = new SqlCommand(rule, cnx)) {
            cmd.CommandType = CommandType.Text;
            
            // Make sure to add values to parameters whenever required by your query.
            // e.g. cmd.Parameters.AddWithValue("@paramName", value);

            cnx.Open();

            using (var dr = cmd.ExecuteReader()) 
                if (dr.HasRows)
                    while (dr.Read()) 
                        if (!dr.IsDBNull(0)) 
                            found.Add(dr.GetStringValue(0));                                        
        }   

    return found;         
}
  1. 检查null 值总是明智的,以便优雅地处理它们。
  2. 设置cmd.CommandType 将告诉ADO.NET 它将如何执行您的命令。
  3. 提供适当的参数(如果有)是强制性的(但事实并非如此,因为它运行时没有错误)。
  4. 始终使用using 块,以便在超出范围时释放您的资源。

using Statement (C# Reference)

提供方便的语法,确保正确使用IDisposable 对象。

IDisposable

提供释放非托管资源的机制。

由于您的程序似乎运行良好,除非您另有说明,否则我无法找出其他错误。


dr.HasRows == false

第一次看到你的 SQL 查询,你的查询超时并不奇怪。

来自 MSDN:

IDbCommand.CommandTimeout Property

获取或设置在终止尝试执行命令并生成错误之前的等待时间。

Remarks (SqlCommand.CommandTimeout Property)

0 表示没有限制(尝试执行命令将无限期等待)。

我看到你试图设置CommandTimeout = 0。除了诊断您的查询是否花费了太长时间之外,您永远不会这样做。

相反,您应该考虑将 timeout 属性设置为您的软件性能要求可以接受的值。尝试计算执行所需的时间,并相应地设置 CommandTimeout

默认值为 30 秒。也许您的查询需要 45 秒或更长时间才能执行。找到有效的方法,这将允许您设置正常的执行时间。然后,当它需要更长的时间时,这将意味着有一些错误,不一定是你的代码。

另外,试着弄清楚你的查询是否可以使用更多的索引等,通过SSAS分析它的执行计划,这将指出你的查询需要最多的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多