T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 14.06.10 02:30
Оценка: 96 (11) :)
В библиотеку добавлен T4 шаблон для генерации модели данных по базе данных. На данный момент сделана поддержка для Sybase и MS SQL.

Использовать следующим образом:

1. Копируем файлы шаблона из папки Source\Templates в свой проект.
2. Добавляем в проект новый файл с расширением tt.
3. Редактируем файл следующим образом:

<#@ template language="C#v3.5"         #>
<#@ output extension=".generated.cs"   #>
<#@ include file="BLToolkit.ttinclude" #>
<#@ include file="Sybase.ttinclude"    #>
<#
    ConnectionString     = "Data Source=DBHost;Port=5000;Database=BLToolkitData;Uid=sa";
    DataProviderAssembly = @"......\Sybase.AdoNet2.AseClient.dll";

    Namespace       = "Templates";
    DataContextName = "DataModel";

    GenerateModel();
#>

С ConnectionString, думаю, всё ясно. В DataProviderAssembly указывается путь к сборке дата провайдера. Если сборка установлена в GAC, то вместо этого можно попробовать воспользоваться следующей директивой:

<#@ assembly name="Sybase.AdoNet2.AseClient" #>

Для MS SQL ничего этого делать не нужно. Т.е. шаблон будет выглядеть следующим образом:

<#@ template language="C#v3.5"         #>
<#@ output extension=".generated.cs"   #>
<#@ include file="BLToolkit.ttinclude" #>
<#@ include file="MSSQL.ttinclude"     #>
<#
    ConnectionString = "Server=.;Database=BLToolkitData;Integrated Security=SSPI";

    Namespace        = "Templates";
    DataContextName  = "DataModel";

    GenerateModel();
#>

В Namespace и DataContextName указываются соответсвенно namespace и имя класса, который будет выступать в качестве DataContext. К сожалению, из шаблонов нельзя просто доступиться к проекту студии и эти параметры нужно задавать вручную. В качестве альтернативы можно установить T4 Toolbox и изменить проект слудующим образом:

<#@ template language="C#v3.5" hostspecific="True" #>
<#@ output extension=".generated.cs"     #>
<#@ include file="BLToolkit.ttinclude"   #>
<#@ include file="BLT4Toolkit.ttinclude" #>
<#@ include file="MSSQL.ttinclude"       #>
<#
    ConnectionString = "Server=.;Database=BLToolkitData;Integrated Security=SSPI";

    GenerateModel();
#>

Теперь эти параметры будут браться из проекта, но на компьютере должен быть установлен T4 Toolbox и работать шаблон будет только из под студии.

Генерация кода для VB делается следующим образом:

<#@ template language="C#v3.5"         #>
<#@ output extension=".generated.vb"   #>
<#@ include file="BLToolkit.ttinclude" #>
<#@ include file="MSSQL.ttinclude"     #>
<#@ include file="VB.ttinclude"        #>
<#
    ConnectionString = "Server=.;Database=BLToolkitData;Integrated Security=SSPI";

    Namespace        = "Templates";
    DataContextName  = "DataModel";

    GenerateModel();
#>

Кроме вышеприведённых настроечных переменных проект поддерживает следующие переменные:

string DataContextName;
string Namespace                = "DataModel";
string BaseDataContextClass     = "DbManager";
string BaseEntityClass          = null;
string OneToManyAssociationType = "IEnumerable<{0}>";
bool   RenderField              = false;

Работа шаблона состоит из двух этапов: чтение метаданных из БД и собственно рендеринг. После чтения метаданных их можно подредактировать по своему усмотрению. Следующий пример демонстрирует некоторые возможности:

<#@ template language="C#v3.5"         #>
<#@ output extension=".generated.cs"   #>
<#@ include file="BLToolkit.ttinclude" #>
<#@ include file="MSSQL.ttinclude"     #>
<#
    ConnectionString = "Server=.;Database=BLToolkitData;Integrated Security=SSPI";

    Namespace        = "Templates";
    DataContextName  = "DataModel";

    // Важно! Этот метод нужно вызвать до начала работы с метаданными.
    //
    LoadMetadata();

    // Меняем имя поля BinaryDataID таблицы BinaryData на ID.
    //
    Tables["BinaryData"].Columns["BinaryDataID"].MemberName = "ID";

    // Меняем имя ассоциации FK_Employees_Employees таблицы Employees на ReportsToEmployee.
    //
    Tables["Employees"].ForeignKeys["FK_Employees_Employees"].MemberName = "ReportsToEmployee";

    // Заменям имя поля на "ID", если это поле является первичным ключом и имеет имя ClassNameID.
    // 
    foreach (var t in Tables.Values)
        foreach (var c in t.Columns.Values)
            if (c.IsPrimaryKey && t.TableName + "ID" == c.ColumnName)
                c.MemberName = "ID";

    // Добавляем наследование entity классам от EntityBase<T>.
    //
    Usings.Add("BLToolkit.Common");

    foreach (var t in Tables.Values)
        t.BaseClassName = "EntityBase<" + t.ClassName + ">";

    GenerateModel();
#>

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

Структура метаданных шаблона выглядит следующим образом:

Dictionary<string,Table> Tables = new Dictionary<string,Table>();

partial class Table
{
    public string       Owner;
    public string       TableName;
    public string       ClassName;
    public string       BaseClassName;
    public bool         IsView;
    public List<string> Attributes = new List<string>();

    public Dictionary<string,Column>     Columns     = new Dictionary<string,Column>();
    public Dictionary<string,ForeignKey> ForeignKeys = new Dictionary<string,ForeignKey>();
}

partial class Column
{
    public int          ID;
    public string       ColumnName;
    public string       MemberName;
    public bool         IsNullable;
    public bool         IsIdentity;
    public string       Type;
    public bool         IsClass;
    public DbType       DbType;
    public SqlDbType    SqlDbType;
    public int          PKIndex = -1;
    public List<string> Attributes = new List<string>();

    public bool IsPrimaryKey { get { return PKIndex >= 0; } }
}

enum AssociationType
{
    Auto,
    OneToOne,
    OneToMany,
    ManyToOne,
}

partial class ForeignKey
{
    public string          KeyName;
    public string          MemberName;
    public Table           OtherTable;
    public List<Column>    ThisColumns  = new List<Column>();
    public List<Column>    OtherColumns = new List<Column>();
    public ForeignKey      BackReference;
    public AssociationType AssociationType;
}

При желании, манипуляции с метаданными можно оформить в виде отдельного файла как это сделано для атрибутов WCF:

<#@ template language="C#v3.5"             #>
<#@ output extension=".generated.cs"       #>
<#@ include file="BLToolkit.ttinclude"     #>
<#@ include file="MSSQL.ttinclude"         #>
<#@ include file="WCFAttributes.ttinclude" #>
<#
    ConnectionString = "Server=.;Database=BLToolkitData;Integrated Security=SSPI";

    Namespace        = "Templates";
    DataContextName  = "DataModel";

    GenerateModel();
#>

Этот шаблон добавляет атрибуты DataContract классам и DataMember свойствам модели и выглядит следующим образом:

<#
    {
        var wcfPrevBeforeGenerateModel = BeforeGenerateModel;
    
        BeforeGenerateModel = tt =>
        {
            wcfPrevBeforeGenerateModel(tt);

            Usings.Add("System.Runtime.Serialization");

            foreach (var t in Tables.Values)
                t.Attributes.AddRange(new[] { "Serializable", "DataContract" });

            foreach (var t in Tables.Values)
                foreach (var c in t.Columns.Values)
                    c.Attributes.Add("DataMember");
        };
    }
#>

Добавить поддержку остальных провайдеров не проблема, но нужно разбираться с тем как читать из низ метаданные. Если у кого-то есть подобная информация, то добавить другие провайдеры будет проще простого.
Если нам не помогут, то мы тоже никого не пощадим.
Re: T4 шаблон для MS SQL и Sybase
От: Legion13  
Дата: 16.06.10 06:15
Оценка: 31 (1)
Здравствуйте, IT, Вы писали:

IT>Добавить поддержку остальных провайдеров не проблема, но нужно разбираться с тем как читать из низ метаданные. Если у кого-то есть подобная информация, то добавить другие провайдеры будет проще простого.

DbLinq знает, у них даже свой инструмент есть, DbMetal (аналог Sqlmetal). Можно подглядеть, или даже заюзать, там вроде бы есть апи к метаданным..
Re[2]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 16.06.10 12:45
Оценка:
Здравствуйте, Legion13, Вы писали:

IT>>Добавить поддержку остальных провайдеров не проблема, но нужно разбираться с тем как читать из низ метаданные. Если у кого-то есть подобная информация, то добавить другие провайдеры будет проще простого.

L>DbLinq знает, у них даже свой инструмент есть, DbMetal (аналог Sqlmetal). Можно подглядеть, или даже заюзать, там вроде бы есть апи к метаданным..

Посмотрим. Спасибо за наводку.
Если нам не помогут, то мы тоже никого не пощадим.
Re: T4 шаблон для MS SQL и Sybase
От: Ziaw Россия  
Дата: 17.06.10 17:58
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>В библиотеку добавлен T4 шаблон для генерации модели данных по базе данных. На данный момент сделана поддержка для Sybase и MS SQL.


Не планируется ли чтение метаданных перенести из T4 шаблонов в тулкит? Мне бы это очень пригодилось.
Re[2]: T4 шаблон для MS SQL и Sybase
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.06.10 18:10
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Не планируется ли чтение метаданных перенести из T4 шаблонов в тулкит? Мне бы это очень пригодилось.


Поищи, вопрос уже обсуждался. Вкратце — все зависит от того, зачем тебе эти метаданные нужны.
... << RSDN@Home 1.2.0 alpha 4 rev. 1474 on Windows 7 6.1.7600.0>>
AVK Blog
Re[2]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 17.06.10 18:25
Оценка:
Здравствуйте, Ziaw, Вы писали:

IT>>В библиотеку добавлен T4 шаблон для генерации модели данных по базе данных. На данный момент сделана поддержка для Sybase и MS SQL.


Z>Не планируется ли чтение метаданных перенести из T4 шаблонов в тулкит? Мне бы это очень пригодилось.


В принципе, можно. Надо только решить куда это лучше затолкать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: T4 шаблон для MS SQL и Sybase
От: Ziaw Россия  
Дата: 17.06.10 18:35
Оценка:
Здравствуйте, AndrewVK, Вы писали:

Z>>Не планируется ли чтение метаданных перенести из T4 шаблонов в тулкит? Мне бы это очень пригодилось.


AVK>Поищи, вопрос уже обсуждался. Вкратце — все зависит от того, зачем тебе эти метаданные нужны.


Для того же что и в шаблонах. Генерации модели по базе, только макросами в немерле. Сейчас я использую янусовский читатель метаданных. Только типы колонок заменил на тулкитовские, они поудобнее. Если чтение метаданых будет в тулките — для работы со схемой мне останется только генерация DDL, которую можно и переписать с нуля.
Re[3]: T4 шаблон для MS SQL и Sybase
От: Ziaw Россия  
Дата: 17.06.10 18:37
Оценка:
Здравствуйте, IT, Вы писали:

IT>В принципе, можно. Надо только решить куда это лучше затолкать.


В провайдеры?
Re[4]: T4 шаблон для MS SQL и Sybase
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.06.10 19:22
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Для того же что и в шаблонах. Генерации модели по базе, только макросами в немерле. Сейчас я использую янусовский читатель метаданных. Только типы колонок заменил на тулкитовские, они поудобнее. Если чтение метаданых будет в тулките — для работы со схемой мне останется только генерация DDL, которую можно и переписать с нуля.


Дело в том, что метаданные разных БД отличаются очень сильно, намного сильнее SQL. Вот те же автоинкрементные поля, к примеру. В янусе там хитрые хаки используются, но для библиотеки это не очень хорошо.
... << RSDN@Home 1.2.0 alpha 4 rev. 1474 on Windows 7 6.1.7600.0>>
AVK Blog
Re[4]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 17.06.10 19:55
Оценка:
Здравствуйте, Ziaw, Вы писали:

IT>>В принципе, можно. Надо только решить куда это лучше затолкать.


Z>В провайдеры?


Видимо туда.
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: T4 шаблон для MS SQL и Sybase
От: Ziaw Россия  
Дата: 18.06.10 04:04
Оценка:
Здравствуйте, AndrewVK, Вы писали:

Z>>Для того же что и в шаблонах. Генерации модели по базе, только макросами в немерле. Сейчас я использую янусовский читатель метаданных. Только типы колонок заменил на тулкитовские, они поудобнее. Если чтение метаданых будет в тулките — для работы со схемой мне останется только генерация DDL, которую можно и переписать с нуля.


AVK>Дело в том, что метаданные разных БД отличаются очень сильно, намного сильнее SQL.


Да, я в курсе.

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


В янусе, афайк, используются хаки для эмуляции таких полей там где их нет. Это действительно геморой.
Re[6]: T4 шаблон для MS SQL и Sybase
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.06.10 04:15
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В янусе, афайк, используются хаки для эмуляции таких полей там где их нет.


Ну вот где то поля, где то генераторы, где то функция специяльная. Полный разброд и шатание.

Z> Это действительно геморой.


Так вот и вопрос, что с этим делать.
... << RSDN@Home 1.2.0 alpha 4 rev. 1474 on Windows 7 6.1.7600.0>>
AVK Blog
Re[7]: T4 шаблон для MS SQL и Sybase
От: Ziaw Россия  
Дата: 18.06.10 14:46
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Ну вот где то поля, где то генераторы, где то функция специяльная. Полный разброд и шатание.

AVK>Так вот и вопрос, что с этим делать.

С чем? С чтением метаданных? Да ничего, если база умеет автоинкрементные колонки флаг IsIdentity у них будет выставлятьтся, если нет — нет.

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

Генераторы достаточно простые, часть делает запрос перед вставкой в БД, часть после, часть получает в качестве резульата инсерта, часть генерит ключ без участия БД.
Все что нужно — атрибут для указания генератора и отдавать генератору запрос и объект перед вставкой и после вставки.

Некоторые генераторы поддерживаются частью доступных БД, некоторые всеми. Есть специальный генератор native, который использует штатный генератор конкретной БД. Пользователь уже сам выбирает какой использовать.
Re: T4 шаблон для MS SQL и Sybase
От: Andy77 Ниоткуда  
Дата: 29.07.10 21:03
Оценка:
Здравствуйте, IT, Вы писали:

IT>В библиотеку добавлен T4 шаблон для генерации модели данных по базе данных. На данный момент сделана поддержка для Sybase и MS SQL.


Очень здорово сделано! А что насчет WCFAttributes? Я добавил этот файл в инклюды, но что-то [DataContract] и [DataMember] атрибуты не появились...

<#@ template language="C#v3.5" #>
<#@ output extension=".generated.cs" #>
<#@ include file="BLToolkit.ttinclude" #>
<#@ include file="WCFAttributes.ttinclude" #>
<#@ include file="MSSQL.ttinclude" #>
Re[2]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 30.07.10 00:55
Оценка: 12 (1)
Здравствуйте, Andy77, Вы писали:

A>Очень здорово сделано! А что насчет WCFAttributes?


Поломалось.

A>Я добавил этот файл в инклюды, но что-то [DataContract] и [DataMember] атрибуты не появились...


Починилось.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: T4 шаблон для MS SQL и Sybase
От: Andy77 Ниоткуда  
Дата: 30.07.10 17:30
Оценка:
IT>Починилось.

Супер! Еще один небольшой реквест — можно ли добавить переменную PluralizeTableNames?
Re[4]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 30.07.10 18:34
Оценка:
Здравствуйте, Andy77, Вы писали:

A>Еще один небольшой реквест — можно ли добавить переменную PluralizeTableNames?


Как это должно работать?
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: T4 шаблон для MS SQL и Sybase
От: Andy77 Ниоткуда  
Дата: 30.07.10 19:42
Оценка:
Здравствуйте, IT, Вы писали:

IT>Как это должно работать?


Да просто добавлять постфикс "s" к именам свойств, представляющих таблицы сущностей — в примере ниже это TdxEvents, TdxEventTypes etc.

public partial class DataModel : DbManager
{
    public Table<TdxEvent>          TdxEvents          { get { return this.GetTable<TdxEvent>();          } }
    public Table<TdxEventType>      TdxEventTypes      { get { return this.GetTable<TdxEventType>();      } }
    public Table<TdxParameter>      TdxParameters      { get { return this.GetTable<TdxParameter>();      } }
    public Table<TdxParameterValue> TdxParameterValues { get { return this.GetTable<TdxParameterValue>(); } }
    public Table<TdxSession>        TdxSessions        { get { return this.GetTable<TdxSession>();        } }
}
Re[6]: T4 шаблон для MS SQL и Sybase
От: IT Россия linq2db.com
Дата: 30.07.10 21:12
Оценка:
Здравствуйте, Andy77, Вы писали:

A>Да просто добавлять постфикс "s" к именам свойств, представляющих таблицы сущностей — в примере ниже это TdxEvents, TdxEventTypes etc.


Как быть с именами вроде Boss и City?
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: T4 шаблон для MS SQL и Sybase
От: MozgC США http://nightcoder.livejournal.com
Дата: 30.07.10 21:31
Оценка:
Здравствуйте, IT, Вы писали:

IT>Как быть с именами вроде Boss и City?


А также Child-Children и т.д.

В принципе есть готовые классы-конвертеры на C#, но это стоит ли это включать в библиотеку.. к тому же все равно может попасться слово где неправильно множественное число образуется..
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.