C# 提高DAL性能

C# 提高DAL性能,c#,performance,idatareader,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.ExecuteReade

我目前填充业务对象的方式与下面的代码片段类似

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包含更多数据库查找,以便完全填充对象。

AFAIK,这是最快的。可能是SQL查询/服务器的速度较慢。或者其他地方。

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

其中,constAiliasId是一个常量,包含字段AiliasId的序号


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

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

public IEnumerable<YourType> SomeMethod(...args...) {
    using(connection+reader) {
        while(reader.Read()) {
            YourType item = BuildObj(reader);
            yield return item;
        }
    }
}
public IEnumerable方法(…参数…){
使用(连接+读卡器){
while(reader.Read()){
YourType item=BuildObj(读卡器);
收益回报项目;
}
}
}
消费代码(通过
foreach
etc)一次只处理一个对象。如果他们想得到一个列表,他们可以(使用新的
list(sequence)
,或者在.NET 3.5中:
sequence.ToList()


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

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

  • 我们跳了多少次到DB?有没有什么方法可以通过使用多个结果集(我们使用存储过程)减少连接频率并带回更大的数据块呢?因此,不是每个子对象都加载自己的数据,而是父对象为自己及其子对象获取所有数据。您可能会遇到脆弱的SQL(需要匹配的排序顺序等)和复杂的循环来遍历DataReader,但我们发现它比多个DB trip更为优化

  • 启动数据包嗅探器/网络监视器,以准确查看有多少数据通过网络传输。您可能会惊讶地看到一些结果集有多大。如果是的话,那么你可以考虑其他解决问题的方法。比如延迟/延迟加载一些子数据

  • 确保你正在使用你所要求的所有结果。例如,从SELECT*from(返回30个字段)到简单地选择Id、Name from(如果这是您所需要的全部)可能会有很大的不同


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

    您是否确实存在性能问题?使用DataReader几乎是实现这一点的最佳和最快的方法-所有其他方法通常都基于DataReader。如果对不同的表有问题,则PopulateFromReader方法中会发生多ul查找。我正在尝试诊断问题所在,无论是DAL、服务器(不太可能)、表结构还是带宽。很好的回答。许多人忘记了GetOrdinal必须做额外的工作才能得到正确的列。我的想法也是。获取读取循环外部的顺序位置。
    public IEnumerable<YourType> SomeMethod(...args...) {
        using(connection+reader) {
            while(reader.Read()) {
                YourType item = BuildObj(reader);
                yield return item;
            }
        }
    }