XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
От: Yuri Abele Германия yabele.blogspot.com
Дата: 28.02.14 12:47
Оценка:
Привет!

Как заставить XSD.EXE генерить такой же C# код, какой генерит Custom Tool "MSDataSetGenerator" в VS?

XSD.EXE для таблиц генерит
public partial class MyTableDataTable : global::System.Data.DataTable, global::System.Collections.IEnumerable


А MSDataSetGenerator в VS генерит

public partial class MyTableDataTable : global::System.Data.TypedTableBase<MyTableRow>


При этом MSDN утверждает, что
TypedTableBase<T> класс ... используется в качестве основного класса для создания типизированных объектов DataTable с помощью Visual Studio и средства XSD.exe .NET Framework.
Но это же не правда!
xsd msdatasetgenerator typedtablebase dataset
Re: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 28.02.14 13:04
Оценка:
Здравствуйте, Yuri Abele, Вы писали:

YA>Как заставить XSD.EXE генерить такой же C# код, какой генерит Custom Tool "MSDataSetGenerator" в VS?


Укажите ключ /enableLinqDataSet
Re[2]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
От: Yuri Abele Германия yabele.blogspot.com
Дата: 28.02.14 13:16
Оценка:
YA>>Как заставить XSD.EXE генерить такой же C# код, какой генерит Custom Tool "MSDataSetGenerator" в VS?
МР>Укажите ключ /enableLinqDataSet
Помогло, спасибо!

Может вы еще сможете подсказать, как "убедить" XSD.EXE генерить тексты комментариев и исключений ВСЕГДА на английском?
А то они генерятся в Visual Studio (MSDataSetGenerator) на английском, а XSD.EXE генерит их на другом языке (в моем случае на немецком).
Re[3]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 28.02.14 13:54
Оценка:
Здравствуйте, Yuri Abele, Вы писали:

YA>Может вы еще сможете подсказать, как "убедить" XSD.EXE генерить тексты комментариев и исключений ВСЕГДА на английском?

На сколько я могу судить, для генерации просто обращается к классу System.Data.Design.TypedDataSetGenerator, который при генерации использует стандартный механизм получения ресурсов (т.е. берет текущую культуру потока).

Поэтому нормальных способов, я честно говоря, не вижу. Сам xsd.exe никаких специальных параметров в командной строке или своем app.config не предоставляет. Стандартных способов указать культуру для консольных приложений я не знаю.

Посему остаются только всякие окольные варианты:
Re[4]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 28.02.14 15:16
Оценка: 31 (3)
Здравствуйте, Михаил Романов, Вы писали:


МР>
  • На скорую руку написать свой аналог xsd.exe, используя System.Data.Design.TypedDataSetGenerator, на первый взгляд там все просто (но это на первый взгляд, как обычно ).

    Кстати, не удержался и попробовал Действительно, все генерируется, и контроль над выходным файлом получается максимальный (т.е. в принципе уже после генерации можно пробежаться по готовому DOM и что-то поправить).
    Единственное, чего не смог проверить — как влияет смена культуры на комментарии: у меня не стоит ни один Language Pack (и комментарии и так на английском).
    Если будет время и возможность — проверьте, пожалуйста, у себя на машине такой вариант:
    const string xsdFileName = @"XMLSchema1.xsd";
    const string outputFileName = @"XMLSchema1.cs";
    const string codeNamespaceString = "MyNamespace";
    const string codeLanguage = "CSharp";
    const string culture = "en-us";
    
    var cultureInfo = new CultureInfo(culture);
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;
    
    var codeUnit = new CodeCompileUnit();
    var codeNamespace = new CodeNamespace(codeNamespaceString);
    var codeProvider = CodeDomProvider.CreateProvider(codeLanguage);
    codeUnit.Namespaces.Add(codeNamespace);
    
    TypedDataSetGenerator.Generate(new StreamReader(xsdFileName).ReadToEnd(), codeUnit, codeNamespace, codeProvider, 
        TypedDataSetGenerator.GenerateOption.LinqOverTypedDatasets);
    
    codeProvider.GenerateCodeFromCompileUnit(codeUnit, new StreamWriter(outputFileName),
        new CodeGeneratorOptions {IndentString = "\t"});
  • Re[5]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Yuri Abele Германия yabele.blogspot.com
    Дата: 03.03.14 10:22
    Оценка:
    Огромное спасибо Михаил, Вы мне очень помогли.
    Я в ближайшие дни попробую Ваш код и напишу о результатах.
    Re[6]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 03.03.14 10:25
    Оценка: :)
    Здравствуйте, Yuri Abele, Вы писали:

    YA>Огромное спасибо Михаил, Вы мне очень помогли.

    Да не вопрос. Что называется, чем бы программист в пятницу не занимался — лишь бы не основной работой

    YA>Я в ближайшие дни попробую Ваш код и напишу о результатах.

    Буду очень признателен — хочется узнать, угадал ли.
    Re[6]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Peshuha Россия  
    Дата: 03.03.14 13:11
    Оценка:
    Здравствуйте, Yuri Abele, Вы писали:

    Присоединяюсь к Спасибу!

    на vb net vs2012, ежели кому надо..

    Imports System.Globalization
    Imports System.Threading
    Imports System.CodeDom
    Imports System.CodeDom.Compiler
    Imports System.IO
    
    Public Class Class1
    
        Public Sub Main()
            generate("DataSet1.xsd", "\DataSet1.vb", "MyNamespace", "VisualBasic", "en-us") '"CSharp"
        End Sub
    
        Public Sub generate(xsdFileName As String, outputFileName As String, ns As String, lng As String, culture As String)
    
    
            Dim cultureInfo As New CultureInfo(culture)
            Thread.CurrentThread.CurrentCulture = cultureInfo
            Thread.CurrentThread.CurrentUICulture = cultureInfo
    
            Dim codeUnit As New CodeCompileUnit()
            Dim codeNamespace As New CodeNamespace(ns)
            Dim codeProvider As CodeDomProvider = CodeDomProvider.CreateProvider(lng)
            codeUnit.Namespaces.Add(codeNamespace)
    
            Dim si As New StreamReader(xsdFileName)
            Dim s As String = System.Data.Design.TypedDataSetGenerator.Generate(si.ReadToEnd(), codeUnit, codeNamespace, codeProvider) '  TypedDataSetGenerator.GenerateOption.LinqOverTypedDatasets
            si.Close()
    
            Dim so As New StreamWriter(outputFileName)
            codeProvider.GenerateCodeFromCompileUnit(codeUnit, so, New CodeGeneratorOptions With {.IndentString = CStr(vbTab)})
            so.Close()
    
        End Sub
    End Class
    ... Мы не привыкли отступать! И расколоть его поможет киножурнал "Хочу Все Знать"! ;)
    Re[7]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 03.03.14 14:18
    Оценка:
    Здравствуйте, Peshuha, Вы писали:

    P>Присоединяюсь к Спасибу!

    Откровенно говоря, даже подумать не мог, что это решение может так пригодится.
    Очень рад.
    Re[5]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Yuri Abele Германия yabele.blogspot.com
    Дата: 03.03.14 20:37
    Оценка:
    Здравствуйте, Михаил

    Да, с подстановкой культуры работает, комментарии тоже тогда из соответствующей культуры. Еще раз спасибо!

    МР>уже после генерации можно пробежаться по готовому DOM и что-то поправить).

    Собственно для этого и затевалось все. Мне необходимо добавить опционально активируемый LOGгинг (в идеале через Log4Net).
    У меня есть уже готовое TypeExtension для OracleCommand:
    (если интересно могу запостить код
    public static class System_Data_OracleClient_OracleCommand
    {
    ...
        public const string PATTERN_PARAM_PLACEHOLDER = ":{ParameterName}";
        public const string PATTERN_PARAM_COMMENT = "/*{ParameterName}*/ ";
    ...
        public static string ToDebugString(this OracleCommand command)
        {
            ...
        }
    }


    которое выдает текст запроса с уже подставленными параметрами:
    SELECT *
    FROM MyTable
    WHERE SomeColumn LIKE /*SomeParam*/ 'ABC'

    Здесь вышеописанная функция расширения подменила PlaceHolder :{SomeParam} и соотв. параметр со значением "ABC" на текст /*SomeParam*/ 'ABC'

    Я хочу использовать эту или подобную функцию, чтобы получить такое (код на VB.NET но будет на C#):
    <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
     Global.System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter"), _
     Global.System.ComponentModel.DataObjectMethodAttribute(Global.System.ComponentModel.DataObjectMethodType.[Select], True)> _
    Public Overridable Overloads Function GetSiteContacts() As GMDB_DA.SCN_SITECONTACTDataTable
        Me.Adapter.SelectCommand = Me.CommandCollection(0)
        Dim dataTable As GMDB_DA.SCN_SITECONTACTDataTable = New GMDB_DA.SCN_SITECONTACTDataTable()
        LOG.Debug(Me.Adapter.SelectCommand.ToDebugString())
        Me.Adapter.Fill(dataTable)
        Return dataTable
    End Function


    Как-то так ...
    Re[6]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 04.03.14 04:34
    Оценка:
    Юрий, добрый день.

    Я откровенно говоря практически не работал с DataSet (и уж точно не работал с генераторами).
    Поэтому уточню: я не нашел в листинге того, что генерирует XSD.EXE никакого намека на метод, генерирующий заполнение DataTable, как в вашем примере. А судя по атрибутам, это именно сгенерированный метод.

    YA>Я хочу использовать эту или подобную функцию, чтобы получить такое (код на VB.NET но будет на C#):

    YA>
    YA><Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
    YA> Global.System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter"), _
    YA> Global.System.ComponentModel.DataObjectMethodAttribute(Global.System.ComponentModel.DataObjectMethodType.[Select], True)> _
    YA>Public Overridable Overloads Function GetSiteContacts() As GMDB_DA.SCN_SITECONTACTDataTable
    YA>    Me.Adapter.SelectCommand = Me.CommandCollection(0)
    YA>    Dim dataTable As GMDB_DA.SCN_SITECONTACTDataTable = New GMDB_DA.SCN_SITECONTACTDataTable()
    YA>    LOG.Debug(Me.Adapter.SelectCommand.ToDebugString())
    YA>    Me.Adapter.Fill(dataTable)
    YA>    Return dataTable
    YA>End Function
    YA>


    Посему возникает подозрение, что разница между XSD.EXE и MSDataSetGenerator несколько шире, чем это видится на первый взгляд.
    Перепроверьте, пожалуйста заранее...
    Re[5]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 04.03.14 04:38
    Оценка:
    Здравствуйте, Михаил Романов, Вы писали:

    МР>>На скорую руку написать свой аналог xsd.exe,


    Все же получилось уж слишком на скорую, поэтому пока далеко не ушли, поправлю сам себя. Все же выходной поток лучше закрывать явно, иначе последние изменения банально не попадут в выходной поток. Посему последнюю строчку нужно заменить на:
    var outStream = new StreamWriter(outputFileName);
    codeProvider.GenerateCodeFromCompileUnit(codeUnit, outStream, new CodeGeneratorOptions {IndentString = "\t"});
    outStream.Close();
    Re[7]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Yuri Abele Германия yabele.blogspot.com
    Дата: 04.03.14 06:46
    Оценка:
    МР>Посему возникает подозрение, что разница между XSD.EXE и MSDataSetGenerator несколько шире, чем это видится на первый взгляд.
    МР>Перепроверьте, пожалуйста заранее...
    Я еще все проверю, но вот что показала декомпиляция XSD.EXE. Этот метод в итоге вызывается, чтобы сгенерить Dataset:

    internal static void GenerateDataSetClasses(string schemaContent, string namespaceName, TextWriter outputWriter, CodeDomProvider codeProvider, bool enableLinqDataSets)
    {
        string str = (string)null;
        try
        {
            CodeCompileUnit compileUnit = new CodeCompileUnit();
            CodeNamespace codeNamespace = new CodeNamespace(namespaceName);
            compileUnit.Namespaces.Add(codeNamespace);
            Xsd.GenerateVersionComment(codeNamespace);
            str = !enableLinqDataSets
                ? System.Data.Design.TypedDataSetGenerator.Generate(schemaContent, compileUnit, codeNamespace, codeProvider)
                : System.Data.Design.TypedDataSetGenerator.Generate(schemaContent, compileUnit, codeNamespace, codeProvider,
                    System.Data.Design.TypedDataSetGenerator.GenerateOption.LinqOverTypedDatasets);
            if (namespaceName == null)
                codeNamespace.Name = str;
            codeProvider.GenerateCodeFromCompileUnit(compileUnit, outputWriter, (CodeGeneratorOptions) null);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(
                Microsoft.DevApps.WebServices.XsdResources.Res.GetString("ErrGenerateDataSetClass", new object[1]
                {
                    (object) str
                }), ex);
        }
    }

    все выглядит очень похоже
    Re[8]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 04.03.14 07:14
    Оценка:
    Здравствуйте, Yuri Abele, Вы писали:

    МР>>Посему возникает подозрение, что разница между XSD.EXE и MSDataSetGenerator несколько шире, чем это видится на первый взгляд.

    МР>>Перепроверьте, пожалуйста заранее...
    YA>Я еще все проверю, но вот что показала декомпиляция XSD.EXE. Этот метод в итоге вызывается, чтобы сгенерить Dataset:

    Да, все верно. Может быть я ввел вас в заблуждение ранее.
    Я тоже декомпилировал именно XSD.EXE, а на MSDataSetGenerator я даже не смотрел (и результаты его работы тоже не видел). Поэтому, как работает студийный генератор я не имею ни малейшего представления
    Re[4]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: AndrewVK Россия http://blogs.rsdn.org/avk
    Дата: 07.03.14 09:29
    Оценка:
    Здравствуйте, Михаил Романов, Вы писали:

    МР>Посему остаются только всякие окольные варианты:


    Можно еще написать тривиальную таску для msbuild, переключающую культуру, и потом написать скрипт с этой таской и таской Xsd.
    ... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
    AVK Blog
    Re[5]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 07.03.14 10:20
    Оценка:
    Здравствуйте, AndrewVK, Вы писали:

    AVK>Можно еще написать тривиальную таску для msbuild, переключающую культуру, и потом написать скрипт с этой таской и таской Xsd.

    В смысле переключить культуру на машине?
    Re[6]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: AndrewVK Россия http://blogs.rsdn.org/avk
    Дата: 08.03.14 08:23
    Оценка:
    Здравствуйте, Михаил Романов, Вы писали:

    МР>В смысле переключить культуру на машине?


    Нет, в текущем потоке.
    ... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
    AVK Blog
    Re[7]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
    Дата: 09.03.14 07:48
    Оценка:
    Здравствуйте, AndrewVK, Вы писали:

    AVK>Нет, в текущем потоке.

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

    Или может Вы говорите не о таске Microsoft.Build.CPPTasks.XSD (из сбореки Microsoft.Build.CPPTasks.Common)? Потому как эта работает через запуск xsd.exe с нужми праметрами командной строки.
    Re[5]: XSD.EXE генерит C# код не такой, как MSDataSetGenerator в VS
    От: Neco  
    Дата: 12.03.14 20:50
    Оценка:
    Здравствуйте, Михаил Романов, Вы писали:

    МР>Кстати, не удержался и попробовал

    Как вариант, можно попробовать подключить xsd.exe к своему проекту (xsd дотнетовский) и дёрнуть публичный метод XsdTool.Xsd.Main (сменив культуру перед этим).
    всю ночь не ем, весь день не сплю — устаю
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.