Как я могу повысить производительность моего приложения, которое генерирует XML с использованием Linq-to-Entities и XElement

#c# #entity-framework #linq-to-entities #linq-to-xml

#c# #entity-framework #linq-to-entities #linq-to-xml

Вопрос:

Я создал приложение, которое генерирует большой XML-файл с использованием Linq-to-Entities и XElement. Это занимает целое ядро нашего сервера с частотой 2 ГГц примерно полчаса и использует ~ 1 ГБ памяти.

Я выполняю следующий тип работы:

 var xml = from x in dbContext.Table1
          select new XElement("Table1",
                     new XElement("Field1", x.Field1),
                     new XElement("Field2", x.Field2),
                     new XElement("Field3", x.Field3),
                     new XElement("MoreFields",
                         new XElement("FieldA", x.MoreFields.FieldA),
                         new XElement("FieldA", x.MoreFields.FieldA),
                         new XElement("FieldA", x.MoreFields.FieldA.DoSomeWorkWithThisField())
    )
);
  

У меня есть еще один или два уровня глубины, и в нескольких полях выполняется работа, например, синтаксический int анализ строки с использованием RegEx.Match()

Есть ли у кого-нибудь какие-либо рекомендации по оптимизации или рефакторингу? Я пытался использовать XStreamingElement , но, похоже, это не имело никакого значения.

Комментарии:

1. Я думаю, что проблема здесь, скорее всего, связана с тем, как вы используете dbcontext. Это рабочий код? Является ли Table1 IQueryable<OfSomething> . Мне это не кажется правильным.

2. Вы правы, я это исправлю. Исправлено

Ответ №1:

Похоже, вы извлекаете все Table1 несколько раз.

Можете ли вы извлечь его в a List<T> , а затем использовать его повторно?

 var list = dbContext.Table1.ToList();
var xml = new XElement("Table1",
    new XElement("Field1", list.Field1),
    new XElement("Field2", list.Field2),
    new XElement("Field3", list.Field3),
    new XElement("MoreFields",
        new XElement("FieldA", list.MoreFields.FieldA),
        new XElement("FieldA", list.MoreFields.FieldA),
        new XElement("FieldA", list.MoreFields.FieldA.DoSomeWorkWithThisField())
    )
);
  

Я подозреваю, что это гораздо сложнее, но в основном — извлеките то, что вам нужно, в память заранее, а затем работайте с этим. Если вам нужно использовать элемент данных только один раз, это можно делать только тогда, когда вам это нужно, но избегайте повторного извлечения одних и тех же данных снова и снова.

Насколько велик документ, который вы создаете, и сколько памяти занимает ваш компьютер? Возможно, вы захотите попробовать посмотреть на счетчики производительности — возможно, вы тратите большую часть времени на сбор мусора.

Комментарии:

1. Спасибо. Я попробую это завтра. У меня сложилось впечатление, что Linq-to-Entities поймет, что я ссылаюсь на одну и ту же таблицу несколько раз, когда она создает операторы SQL. Знаете ли вы какой-нибудь хороший материал для чтения по использованию Linq-to-Entities для генерации XElements ?

Ответ №2:

Для больших документов вам следует рассмотреть потоковое решение, например XmlWriter , вместо решения, подобного XDocument которому, все данные хранятся в памяти.