3

我有以下代码查询数据库并填充数据表。

private DataTable Run(string sql)
    {
        var conn = new OdbcConnection();

        string connString = "[myConnString];";

        conn.ConnectionString = connString;
         conn.Open();

        var da = new OdbcDataAdapter {SelectCommand = conn.CreateCommand()};
        da.SelectCommand.CommandText = sql;
        var dt = new DataTable();
        da.Fill(dt);
        da.Dispose();
        conn.Close();

        return dt;
    }

我刚刚在它上面运行了一个分析器,它表明这条线需要很长时间:

 da.Fill(dt);

该查询仅返回大约 1000 行。以下是本次通话中 .net 内部发生的情况的详细资料:

在此处输入图像描述

鉴于我正在运行一个查询,将其转换为数据表,然后将该表转换为对象列表,我可以做些什么来优化它(以某种方式直接从数据适配器转换为对象列表??) . 我基本上是在寻找解决此代码中此性能瓶颈的方法?

4

4 回答 4

2

我认为确保您的查询快速运行就是答案。代码不能更快,但优化查询可以产生巨大的差异。您可以使用 SQL 探查器并检查原始 SQL 查询的执行吗?

例如添加数据库索引或返回更少的列。网络延迟也可能导致缓慢。数据库是否与正在执行的代码位于同一局域网上?

于 2011-07-08T05:10:39.887 回答
1

我建议使用 OdbcDataReader 和 Transform 函数。像下面这样的东西应该可以工作:

public class OdbcQuery
{
    OdbcCommand Command { get; set; }

    public OdbcQuery(OdbcConnection connection, string cmdText)
    {
        Command = new OdbcCommand(cmdText, connection); 
    }

    public List<T> Transform<T>(Func<OdbcDataReader, T> transformFunction)
    {
        Command.Connection.Open();

        OdbcDataReader reader = Command.ExecuteReader(CommandBehavior.Default);

        List<T> tList = new List<T>();

        while (reader.Read())
        {
            tList.Add(transformFunction(reader));
        }

        Command.Connection.Close();

        return tList; 
    }
}

这是一个示例转换函数,它将为查询中的每一行创建一个类型为 T 的实例。在这种情况下,它只是一个 Foo 对象,

public class Foo
{
    public Foo() { }

    public string FooString { get; set; }
    public int FooInt { get; set; }
}

class Program
{
    public static List<Foo> GetFooList(string connectionString, string cmdText)
    {
        OdbcQuery query = new OdbcQuery(new OdbcConnection(connectionString), cmdText);

        List<Foo> fooList = query.Transform(
            rdr =>
            {
                Foo foo = new Foo();

                foo.FooInt = rdr.GetInt32(0);
                foo.FooString = rdr.GetString(1); 

                return foo; 
            });

        return fooList; 
    }

这应该表现良好,因为您的特定于域的对象是在第一次通过数据库结果时创建的,不需要第二或第三个翻译阶段。

于 2011-07-08T05:27:11.797 回答
0

如果您正在寻找速度,请不要使用数据集/数据适配器,它们是一种旧技术,不是为速度而构建的。使用像 Sean 建议的数据阅读器。

于 2011-07-08T05:29:47.123 回答
0

除了 DataReader,您还可以检查您的查询是否设计良好。

也许您可以对其进行优化或将其拆分为多个并行操作

于 2011-07-08T05:33:13.990 回答