3

我目前填充业务对象的方式是使用类似于下面的代码段的东西。

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

4

5 回答 5

7

一个明显的变化是替换这种语句: ailias.AiliasId = reader.GetInt32(reader.GetOrdinal("AiliasId"));

ailias.AiliasId = reader.GetInt32(constAiliasId);

其中 constAiliasId 是一个保持字段 AiliasId 序数的常量。

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

于 2009-07-27T11:02:50.473 回答
5

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

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

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

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

于 2009-07-27T11:06:25.567 回答
1

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

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

  2. 启动数据包嗅探器/网络监视器,以准确查看通过网络传输的数据量。您可能会惊讶地发现某些结果集有多么庞大。如果是,那么您可能会考虑解决问题的替代方法。就像延迟/延迟加载一些子数据一样。

  3. 确保您正在使用您要求的所有结果。例如,从 SELECT * FROM(返回 30 个字段)到简单的 SELECT Id, Name FROM(如果您只需要这些)可能会产生很大的不同。

于 2009-07-27T11:26:53.327 回答
0

AFAIK,这是最快的。也许缓慢是在 SQL 查询/服务器中。或者别的地方。

于 2009-07-27T11:00:47.030 回答
0

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

于 2009-07-27T12:31:44.427 回答