循环LINQ数据的更快捷方式

时间:2010-10-22 13:21:01

标签: .net xml vb.net linq linq-to-sql

我正在编写从数据库表中提取数据并将其写入XML文件的代码(由另一个进程获取)。有大约60,000条记录,每条记录可以有多个参与者,即一个成员可以有多个联系人,每个联系人可以有几个电话号码等。整个过程需要几个小时,我已经将实际的缓慢范围缩小到了拉取数据(不写XML,或拉动后的任何数据处理等)。我用两种不同的方式尝试了代码,结果相似。首先,我利用LINQ查询并在一个语句中创建所有元素:

Dim output =
    From m In dc.members
    Select New XElement("member", _
        New XElement("id", m.member_id), _
        New XElement("address", m.Address), _
        New XElement("city", m.City), _
        New XElement("state", m.State), _
        New XElement("contacts", _
            From c in m.contacts
            Select New XElement("contact", _
                New XElement("contact_name", c.name), _
                New XElemdnt("contact_address", c.address), _
...

我认为可能是所有XElements的创建减慢了速度,所以我尝试使用For循环将元素直接写入XML文件:

Dim output As New Xml.XmlTextWriter("my.xml", Nothing)
For Each m in dc.members
    output.WriteStartElement("member")
    output.WriteElementString("id", m.member_id)
    output.WriteElementString("address", m.Address)
    output.WriteElementString("city", m.City)
    output.WriteElementString("state", m.State)
    output.WriteStartElement("contacts")
    For Each c in m.contacts
        output.WriteStartElement("contact")
        output.WriteElementString("contract_name", m.name)
        output.WriteElementString("contract_address", m.address)
....

这使得该过程花费的时间几乎没有变化。然后我尝试剥离所有元素并将代码缩减到数据库拉动,同样慢。

是否有更快/更好的方法从数据库中提取所有这些规范化数据,以便我可以尽快将其转换为XML文件?

3 个答案:

答案 0 :(得分:4)

内循环的每次传递都是命中数据库。使用LINQ表达式仅在一次点击中获取所需的数据。在C#中(抱歉,我不知道VB.Net)它看起来像是:

var members = from m in dc.members
              select new {
                  m.member_id,
                  m.Address,
                  ...
                  contacts = from c in m.contacts
                             select new {
                                 c.name,
                                 c.address
                             }
              };
var output = from m in members
             select new XElement...

作为旁注,您可以在VB.Net中使用XML语法......

Dim output = _
    From m In members _
    Select <member>
        <id><%= m.member_id %></id>
        <address><%= m.Address %></address>
        ...
        <contacts>
            <%= From c in m.contacts _
                Select <contact>
                    <contact_name><%= c.name %></contact_name>
                    <contact_address><%= c.address %></contact_address>
                    ...
                </contact>
            %>
        </contacts>
    </member>

答案 1 :(得分:2)

我认为您的问题是Linq的延迟加载

我要做的第一件事就是运行SQL事件探查器并查明是否是这种情况,并且打开和关闭了数千个连接,以访问每个级别的数据。

如果是这种情况,我会废弃Linq并使用SqlDataReader,这可能需要几秒钟来完成这项工作。

如果在探查器和SQL端的一个大查询很慢,我将查看索引并优化数据库索引。

答案 2 :(得分:1)

由于上述原因,这应该明显加快

Dim output =
   From m In dc.members.**Include("contacts")**
   Select New XElement("member", _
      New XElement("id", m.member_id), _
      New XElement("address", m.Address), _
      New XElement("city", m.City), _
      New XElement("state", m.State), _
      New XElement("contacts", _
          From c in m.contacts
          Select New XElement("contact", _
              New XElement("contact_name", c.name), _
              New XElemdnt("contact_address", c.address)
             .....)**.tolist()**

它将在一个db访问调用中选择所有内容而不是N + 1

你也可以尝试并行linq ..这样的东西......我没有可用的编辑器。

dim output = from m in dc.members.asparallel().select(function (m)  new XElement("member", New XElement("id", m.member_id), etc..)