在没有for循环的情况下将数据写入xml

时间:2014-07-18 10:44:36

标签: c# asp.net xml linq-to-xml nopcommerce

我正在开发NopCommerce 2.40,并尝试使用c#生成站点地图,将其提交给Google网站管理员工具。

我的代码

_writer = new XmlTextWriter(stream, Encoding.UTF8);
            _writer.Formatting = Formatting.Indented;
            _writer.WriteStartDocument();
            _writer.WriteStartElement("urlset");
            _writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
            _writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            _writer.WriteAttributeString("xsi:schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd");

            GenerateUrlNodes();

            _writer.WriteEndElement();
            _writer.Close();

在这个GenerateUrlNodes()方法中,调用了不同的方法 e.g

            WriteStores();
            WriteStoresCategories();
            WriteStoresProducts();

第三种写商店产品的方法。

foreach (var store in stores)
            {

                //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
                 if (store.Id != 1)
                 {
                         var products = _productService.SearchProducts(0, 0, null, null, null, 0, null, false, 1, new List<int>(), ProductSortingEnum.Position, 0, int.MaxValue, store.Id, false);
                         foreach (var product in products)
                         {
                             var url = string.Format("{0}s/{1}/{2}/p/{3}/{4}", _webHelper.GetStoreLocation(false), store.Id, store.GetSeName(), product.Id, product.GetSeName());
                             var updateFrequency = UpdateFrequency.Weekly;
                             var updateTime = product.UpdatedOnUtc;
                             WriteUrlLocation(url, updateFrequency, updateTime);


                         }

                 }
            }

由于每个商店都有5到6k种产品的多个商店,因此花费的时间太长了。因此,当我尝试将此站点地图提交给google时,它会抛出超时错误。有没有办法优化这个或避免循环生成xml

有人可以帮我吗?

1 个答案:

答案 0 :(得分:3)

这里要做的第一件事是删除冗余。您似乎每个产品调用_webHelper.GetStoreLocation(false)一次,每个产品调用store.GetSeName()两次 - 但两者都不取决于产品。所以作为一个直接的事情:

var location = _webHelper.GetStoreLocation(false);
foreach (var store in stores)
{
     var seName = store.GetSeName();
    //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
     if (store.Id != 1)
     {
         var products = _productService.SearchProducts(0, 0, null, null, null, 0, null, false, 1, new List<int>(), ProductSortingEnum.Position, 0, int.MaxValue, store.Id, false);
         foreach (var product in products)
         {
             var url = string.Format("{0}s/{1}/{2}/p/{3}/{4}", location, store.Id, seName, product.Id, seName);
             var updateFrequency = UpdateFrequency.Weekly;
             var updateTime = product.UpdatedOnUtc;
             WriteUrlLocation(url, updateFrequency, updateTime);
         }
     }
}

SearchProducts显然是每个商店,因为它涉及store.Id,因此我们无法推广;然而,看起来stores循环可以简单地并行化;例如,如果这是进行http调用,那么在这里调查Parallel.ForEach是值得的,但问题就变成了排序和并发;您可能需要使用Parallel创建每个结果(作为字符串或类似字符串),然后当所有字符串都可用时,循环显示它们进行实际写入 - 从而保留原始顺序。