2

我想重构这段代码,因为它看起来很浪费、古怪和奇怪:

public string getVersion()
{
    try
    {
        string dynSQL = "SELECT * FROM invHeader";
        DataSet workSites = dbconn.getDataSet(dynSQL);

        //Go thru dataset and display the working files
        //Only need one, although we'll be duplicating the version
        //per each site as a check value during upgrades
        //return workSites.Tables[0].Rows
        foreach (DataRow row in workSites.Tables[0].Rows)
        {
            sVersion = row["ID"].ToString();
            break;
        }
    }
    catch (Exception ex)
    {
        Duckbill.ExceptionHandler(ex, "InvHeader.getVersion");
    }

    return sVersion;
} // getVersion

我在想我可以把它改成这样:

public string getVersion()
{
    try
    {
        string dynSQL = "SELECT FIRST ID FROM invHeader"; // I also tried "SELECT 1 ID FROM invHeader"
        DataSet workSites = dbconn.getDataSet(dynSQL);
        return workSites.Tables[0].Rows[0]["ID"].ToString();
    }
    catch (Exception ex)
    {
        Platypus.ExceptionHandler(ex, "InvHeader.getVersion");
    }
} // getVersion

...但是两个查询都没有返回我想要的(第一行中 ID 的值)。那么执行此操作的 SQL 是什么。

顺便说一句,我知道这应该是某种标量调用,但是在这些相互依赖的自产自滚方法中发生了很多时髦的 Rube Goldbergesque 事情,我不敢碰;不过,这个小小的清理工作应该是可行的,不会让我的战利品发抖。

更新

我想我急于获得答案 - SQL Server CE 查询分析器中的“SELECT TOP 1 ID FROM invHeader”导致:

FAILED: SELECT TOP 1 ID FROM invHeader 
Error: x800...._E_ERRORSINCOMMAND
Native Error: (25501)
Description: There was an error parsing the query. [Token line number, Token line offset, Token in error,,]
Interface defining error: IID_ICommand
Paaram. 0:1
Param. 1: 8
Param. 2:0
Param. 3: TOP
Param. 4:
Param. 5:

这似乎很神秘,但我知道的一件事是 SQL Server CE 查询分析器“不好玩”。

更新 2

我发现了这种类似代码的更令人震惊的气味;不仅方法的名称使您相信它返回一个值(嗯,确实如此,这是真的);但是在这样做的同时,它会从一个可能很大的表中获取所有记录,以便简单地(再次)获取第一个记录。

写这篇文章的猫真的有可能没有收到关于“SELECT *”的挥霍使用的备忘录警告吗?

我可以在代码混淆竞赛中提交匿名参赛作品吗?

public string getINVSite()
{
    string  siteStr   = "";
    string  dSQL      = "";
    DataSet workSites;

    dSQL      = "SELECT * FROM inventory";
    dbconn    = DBConnection.GetInstance();
    workSites = dbconn.getDataSet( dSQL );

#if true
//            DataRow row = workSites.Tables[0].Rows[0];

    siteStr = "1";
    if (workSites.Tables.Count > 0)
    {
        if(workSites.Tables[0].Rows.Count>0)
            siteStr = workSites.Tables[0].Rows[0]["ID"].ToString();
    }
    return( siteStr );
#else
    //Go thru dataset and display the working files
    foreach( DataRow row in workSites.Tables[0].Rows )
    {
        return( row["ID"].ToString() );
    }

    return( "" );
#endif
} // getINVSite

现在你知道我背负的重担了;如果感动,请捐赠给您选择的慈善机构。

更新 3

对不起,ctacke;感谢您的帮助,但这太兔子洞了;原始代码,虽然值得疯帽匠,但有效;我有更臭的鱼要炸,所以我会留下它,至少现在是这样。我试过这个:

public string getVersion()
{
    string conStr = "Data Source = " + dbconn.filename;
    MessageBox.Show(string.Format("conStr in InvHeader.getVersion() is {0}", conStr));//TODO: Remove after testing
    try
    {
        using (SqlCeConnection connection = new SqlCeConnection(conStr))
        {
            connection.Open();
            using (SqlCeCommand command = new SqlCeCommand("SELECT ID FROM invHeader", connection))
            using (SqlCeDataReader reader = command.ExecuteReader())
            {
                if (reader.Read())
                {
                    string s = reader.GetString(0);
                    MessageBox.Show(string.Format("version InvHeader.getVersion() is {0}", s));//TODO: Remove after testing
                    return s;// reader.GetString(0);
                }
                else
                {
                    // no result
                    return null;
                }
            }
        }
    }
    catch (Exception ex)
    {
        Pterodactyl.ExceptionHandler(ex, "InvHeader.getVersion");
        return string.Empty;
    }
}

...我仍然有一个例外;在第一个 MessageBox.Show() 中看到连接字符串后,我没有看到第二个。

4

4 回答 4

4

在 MS SQL Server CE 中,它是TOP (N)

SELECT TOP (1) ID 
FROM invHeader 
ORDER BY ???

ORDER BY如果您不希望返回任意记录。

于 2013-09-19T21:50:34.523 回答
3

不要使用数据集。曾经。

下面是一个很好的第一关。如果通过 TableDirect 对 id 字段进行索引,它可能会更快,但我会先运行它以查看性能是否可以接受。

public string GetVersion()
{
    using (var connection = new SqlCeConnection("my connection string"))
    {
        connection.Open();
        using (var command = new SqlCeCommand("SELECT id FROM invHeader", connection))
        using (var reader = command.ExecuteReader())
        {
            if (reader.Read())
            {
                return reader.GetString(0);
            }
            else
            {
                // no result
                return null;
            }
        }
    }
}
于 2013-09-19T23:09:23.297 回答
2

从 invHeader 中选择前 1 个 ID

于 2013-09-19T21:50:33.067 回答
2

避免使用 DataSet,使用 SqlCommand 和 ExecuteScalar 方法。

已编辑

这段代码应该是等效的、功能性的并且更快:

public string getVersion()
{
    try
    {
        // Use TOP (N) http://technet.microsoft.com/en-us/library/bb686896.aspx
        string dynSQL = "SELECT TOP (1) ID FROM invHeader";
        return (string)(new SqlCeCommand(dynSQL, dbconn.getConnection()).ExecuteScalar());
    }
    catch (Exception ex)
    {
        Platypus.ExceptionHandler(ex, "InvHeader.getVersion");
    }
} // getVersion   

假设 dbconn 是一个可以为您提供调用 dbconn.getConnection() 的 SqlCeConnection 的类。

于 2013-09-19T22:23:12.327 回答