提高DAL性能

时间:2009-07-27 10:57:21

标签: c# performance idatareader

我目前填充业务对象的方式是使用与下面的代码段相似的内容。

using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.CDRDatabase))
{
    using (SqlCommand comm = new SqlCommand(SELECT, conn))
    {
        conn.Open();

        using (SqlDataReader r = comm.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (r.Read())
            {
                Ailias ailias = PopulateFromReader(r);
                tmpList.Add(ailias);
            }
        }
    }
}

private static Ailias PopulateFromReader(IDataReader reader)
{
    Ailias ailias = new Ailias();

    if (!reader.IsDBNull(reader.GetOrdinal("AiliasId")))
    {
        ailias.AiliasId = reader.GetInt32(reader.GetOrdinal("AiliasId"));
    }

    if (!reader.IsDBNull(reader.GetOrdinal("TenantId")))
    {
        ailias.TenantId = reader.GetInt32(reader.GetOrdinal("TenantId"));
    }

    if (!reader.IsDBNull(reader.GetOrdinal("Name")))
    {
        ailias.Name = reader.GetString(reader.GetOrdinal("Name"));
    }

    if (!reader.IsDBNull(reader.GetOrdinal("Extention")))
    {
        ailias.Extention = reader.GetString(reader.GetOrdinal("Extention"));
    }

    return ailias;
}

有没有人有任何关于如何提高此类效果的建议?请记住,对于某些类型,PopulateFromReader包含更多数据库查找,以便完全填充对象。

5 个答案:

答案 0 :(得分:7)

一个明显的变化是取代这种陈述:     ailias.AiliasId = reader.GetInt32(reader.GetOrdinal(“AiliasId”));

ailias.AiliasId = reader.GetInt32(constAiliasId);

其中constAiliasId是持有AiliasId字段序数的常量。

这避免了循环的每次迭代中的序数查找。

答案 1 :(得分:5)

如果数据量很高,那么构建庞大列表的开销可能会成为瓶颈;在这种情况下,使用流对象模型可能更有效;即。

public IEnumerable<YourType> SomeMethod(...args...) {
    using(connection+reader) {
        while(reader.Read()) {
            YourType item = BuildObj(reader);
            yield return item;
        }
    }
}

消费代码(通过foreach等)然后只有一个对象要处理(一次)。如果他们想要获取列表,他们可以(使用新的List<SomeType>(sequence)或.NET 3.5:sequence.ToList())。

这涉及到一些方法调用(每个序列项的额外MoveNext() / Current,隐藏在foreach后面),但是当你没有时,你永远不会注意到这一点 - 处理数据,例如来自数据库。

答案 2 :(得分:1)

您的代码与我们的许多业务对象加载函数几乎完全相同。当我们怀疑DAL性能问题时,我们会看一些事情。

  1. 我们多少次跳到数据库?有没有什么方法可以减少连接并通过使用多个结果集(我们使用存储过程)来恢复更大的数据块。所以,不是每个子对象加载自己的数据,父进程将为自己获取所有数据和它的孩子们。您可以遇到脆弱的SQL(需要匹配的排序等)和棘手的循环来遍历DataReaders,但我们发现它比多次数据库访问更加优化。

  2. 启动数据包嗅探器/网络监视器,以确切了解通过线路传输的数据量。您可能会惊讶地看到一些结果集有多大。如果是,那么您可能会考虑解决问题的其他方法。像延迟/延迟加载一些子数据一样。

  3. 确保您使用的是所有要求的结果。例如,从SELECT * FROM(返回30个字段)到简单的SELECT Id,Name FROM(如果这就是你所需的全部)可以产生很大的不同。

答案 3 :(得分:0)

AFAIK,它的速度和它一样快。也许缓慢是在SQL查询/服务器中。或者其他地方。

答案 4 :(得分:0)

真正的问题可能是您提到的多个每个对象的查找。您是否仔细查看过它们是否可以全部放入单个存储过程中?