Вопрос

Я провожу некоторые эксперименты с Microsoft Dynamics CRM.Вы взаимодействуете с ним через веб-сервисы, и я добавил в свой проект веб-ссылку.Интерфейс веб-сервиса очень богат, а сгенерированный файл «Reference.cs» занимает около 90 тыс. мест.

Я использую веб-ссылку в консольном приложении.Я часто что-то меняю, перекомпилирую и запускаю.Компиляция происходит быстро, но обновление ссылки на веб-сервис происходит очень медленно и занимает около 15-20 секунд: CrmService service = new CrmService(); Профилирование показывает, что все время тратится на конструктор SoapHttpClientProtocol.

Виновником, по-видимому, является тот факт, что код сериализации XML (не включенный в упомянутый выше блок 90k) генерируется во время выполнения перед JIT-обработкой.Это происходит во время вызова конструктора.Ожидание довольно неприятно, когда играешь и пробуешь что-то.

Я пробовал различные комбинации sgen.exe, ngen и XGenPlus (что занимает несколько часов и генерирует 500 МБ дополнительного кода), но безрезультатно.Я рассматривал возможность реализации службы Windows, имеющей несколько экземпляров CrmService, готовых к использованию при необходимости, но это кажется чрезмерным.

Есть идеи?

Это было полезно?

Решение

Из этой темы на форумах VMWare извлекается следующее:

Привет, ребята,

Мы обнаружили, что sgen.exe работает. Просто есть несколько дополнительных шагов помимо предварительной генерации dll-файлов сериализатора, которые мы пропустили в этой теме. Вот подробная инструкция

ПРОБЛЕМА

При использовании VIM 2.0 SDK из .NET требуется длительное время для создания экземпляра класса VimService. (Класс VimService - это прокси-класс, сгенерированный с помощью запуска wsdl.exe vim.wsdl vimService.wsdl)

Другими словами, следующая строка кода:

_service = new VimService();

Выполнение может занять около 50 секунд.

ПРИЧИНА

Очевидно, что .NET XmlSerializer использует атрибуты System.Xml.Serialization. * , аннотирующие прокси-классы для генерации кода сериализации во время выполнения. Когда прокси-классов много и много, как в VimService.cs, генерация кода сериализации может занять много времени.

Решение

Это известная проблема с работой сериализатора Microsoft .NET.

Вот некоторые ссылки, которые MSDN предоставляет для решения этой проблемы:

http://msdn2.microsoft.com/en-us/library/ bk3w6240.aspx http://msdn2.microsoft.com/en-us /library/system.xml.serialization.xmlserializerassemblyattribute.aspx

К сожалению, ни одна из вышеперечисленных ссылок не описывает полное решение проблемы. Вместо этого они сосредоточены на том, как предварительно сгенерировать код сериализации XML.

Полное исправление включает в себя следующие шаги:

<Ол>
  • Создать сборку (DLL) с предварительно сгенерированным кодом XML-сериализатора

  • Удалите все ссылки на атрибуты System.Xml.Serialization. * из прокси-кода (т. е. из файла VimService.cs)

  • Аннотируйте основной прокси-класс с помощью атрибута XmlSerializerAssemblyAttribute, чтобы указать, где находится сборка XML-сериализатора.

  • Пропуск шага 2 приводит только к 20% -ному улучшению времени создания класса VimService . Пропуск шага 1 или 3 приводит к неправильному коду. За все три этапа достигается улучшение на 98%.

    Вот пошаговые инструкции:

    Прежде чем начать, убедитесь, что вы используете инструменты .NET версии 2.0. Это решение не будет работать с версией 1.1 .NET, поскольку инструмент sgen и XmlSerializationAssemblyAttribute доступны только в версии 2.0 .NET

    <Ол>
  • Создайте файл VimService.cs из WSDL, используя wsdl.exe:

    wsdl.exe vim.wsdl vimService.wsdl

    Это выведет файл VimService.cs в текущий каталог

  • Скомпилируйте VimService.cs в библиотеку

    csc / t: library /out:VimService.dll VimService.cs

  • Используйте инструмент sgen для предварительной генерации и компиляции сериализаторов XML:

    sgen / p VimService.dll

    Это выведет VimService.XmlSerializers.dll в текущий каталог

  • Вернитесь в файл VimService.cs и удалите все атрибуты System.Xml.Serialization. * . Поскольку код кода большой, лучший способ достичь этого - использовать какой-либо инструмент подстановки регулярных выражений. Будьте осторожны при этом, потому что не все атрибуты появляются в строке сами по себе. Некоторые встроены как часть объявления метода.

    Если вам сложно выполнить этот шаг, вот упрощенный способ сделать это:

    Предполагая, что вы пишете на C #, выполните глобальную замену следующей строки:

    <код> [System.Xml.Serialization.XmlIncludeAttribute

    и замените его на

    // [System.Xml.Seri

  • Другие советы

    Возможно, вы захотите заглянуть в <код> Sgen.exe , поставляемый с .NET. В свойствах проекта Visual Studio C # есть небольшая удобная штука " Build " в самом низу страницы «Сборка сборки сериализации» который автоматически запускает Sgen для вас.

    Я считаю, что это не проблема SGEN. Я посмотрел на код конструктора и вижу, что он много размышляет (основан на XmlIncludeAttribute в классе). Это отражается на всех них и может занять очень много времени.

    Существует предварительно сгенерированная сборка XmlSerializer, которая поставляется с CRM. Проверьте, есть ли у вас в GAC файлы SdkTypeProxy.XmlSerializers.dll и SdkProxy.XmlSerializers.dll.

    Если этого не сделать, это означает, что при создании CrmService .net сгенерирует сборку XmlSerializer, что может занять некоторое время. Надеюсь, это поможет

    Я наткнулся на эту тему, когда пытался выяснить, почему мои первоначальные вызовы SoapHttpClientProtocol занимали так много времени.

    Я обнаружил, что установка прокси-сервера на ноль / пустое состояние остановила автоматическое обнаружение прокси - это занимало до 7 секунд при первоначальном вызове:

    this.Proxy = GlobalProxySelection.GetEmptyWebProxy();
    

    Я использовал приведенный выше подробный ответ в качестве руководства и сделал несколько шагов вперед, создав сценарий для автоматизации процесса.Скрипт состоит из двух файлов:

    генерировать прокси.bat:

    REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
    set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin
    
    wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
    PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
    csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
    sgen /p references\VIM_Service.dll /force REM generate serializtion dll
    

    генерировать прокси.ps1

    (Get-Content VIM.cs) | 
        ForEach-Object { 
            $_ -replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" `
                -replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" `
                -replace "using System;", "namespace Classes.WS_VIM {   `n`nusing System;"
        } |
    Set-Content VIM.cs
    Add-Content VIM.cs "`n}"
    

    Я добавил эти два файла в клиентский проект, а в событии перед сборкой добавил строки

    cd..\..
    generateproxy
    

    Таким образом, перед каждой сборкой прокси-классы перегенерируются, и разработчику (почти) не нужно об этом думать.Во время сборки WS должен быть запущен и работать, а его URL-адрес должен находиться в bat-файле.В результате предварительной сборки два файла DLL будут восстановлены в подпапке клиентского проекта. Рекомендации.После первого выполнения скриптов необходимо добавить ссылку на новую dll.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top