C#程序未从SQL查询中获取结果
本文关键字:获取 结果 查询 SQL 程序 | 更新日期: 2023-09-27 18:27:10
我用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
)
)
)
我试过在microsoftsqlservermanagementstudio中运行这个,它运行得很好。
编辑
正如Will建议的那样,我已经尝试将代码更改为
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;
dr.HasRows是错误的
不过我还是有同样的行为。它适用于其他查询,但不适用于我发布的查询。但是,当在SQL server中运行时,此查询确实有效。
以下是您的代码的相似之处。
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;
}
- 检查
null
值总是明智的,以便优雅地处理它们 - 设置
cmd.CommandType
将告诉ADO.NET如何执行您的命令 - 提供适当的参数(如果有的话)是强制性的(但事实并非如此,因为它运行时没有错误)
- 始终使用
using
块,以便在超出范围时处理您的资源
使用语句(C#参考)
提供一种方便的语法,确保正确使用
IDisposable
对象
IDisposable
提供用于释放非托管资源的机制
由于你的程序运行得很好,除非你另有说明,否则我无法找出其他问题。
dr.HasRows==false
第一次看到您的SQL查询,您的查询超时对我来说并不奇怪。
来自MSDN:
IDbCommon.CommandTimeout属性
获取或设置终止执行命令的尝试并生成错误之前的等待时间
备注(SqlCommand.CommandTimeout属性)
值为0表示没有限制(尝试执行命令将无限期等待)
我看到你试图设置CommandTimeout = 0
。除非诊断您的查询是否花费太长时间,否则您永远不会这样做。
相反,您应该考虑将超时属性设置为软件性能要求可以接受的值。尝试计算执行所需的时间,并相应地设置CommandTimeout。
默认值为30秒。也许您的查询需要45秒或更长时间才能执行。找到有效的方法,这将允许您设置正常执行时间。然后,当它需要更长的时间时,这将意味着有一些错误,不一定是您的代码。
此外,试着弄清楚您的查询是否可以使用更多的索引等,通过SSAS分析其执行计划,这将指出查询中需要花费最多时间的内容。