Разрешить конфликт соглашения об именах между сущностями в EF4 и стандартами нашей базы данных? - PullRequest
2 голосов
/ 13 июля 2011

Я расследую вопрос о замене или дополнении нашей собственной системы ORM на Entity Framework 4 и замечаю, что последняя может привести к конфликту между тем, что мы определили как соглашения об именах для нашего программного кода и наши базы данных. Будучи магазином Microsoft, мы в значительной степени решили следовать руководящим указаниям Microsoft по именованию для нашего кода , в которых говорится об использовании оболочки Pascal для членов, пространств имен и т. Д .; избегать подчеркивания и т. д.

Соглашения по именованию сущностей по умолчанию в EF4, что неудивительно, прекрасно работают с этими стандартами. Например, объект с именем SalesOrder создаст класс с именем SalesOrder и набор объектов с именем SalesOrders . Конструкция EF4 Model-First по умолчанию создает таблицу с тем же именем, что и набор сущностей (в этом примере сгенерированное имя таблицы - SalesOrders). Однако стандарты нашей базы данных предлагают использовать все строчные и подчеркивания между словами (например, sales_orders ). Таким образом, использование Entity Framework «как есть» заставит нас начать отклоняться от них.

Есть ли где-нибудь в Entity Framework, где вы можете переопределить его поведение, использовать имя набора сущностей в качестве имени таблицы SQL? Я не могу найти очевидное место для указания альтернативного имени таблицы для сгенерированного сценария SQL. Если мы пойдем дальше с использованием EF4, является ли единственно вероятным решением заставить нас пересмотреть наши соглашения об именах баз данных?

Обновление:

Я пытаюсь найти решение Ладислава, описанное ниже, но не могу получить опцию Создать базу данных из модели в конструкторе моделей Entity Framework для распознавания моей пользовательской утилиты. У меня есть файл с именем MyOrg.EF.Utility.CS.ttinclude в папке:

%VSINSTALLDIR%\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\Templates\Includes

По сути, это выглядит так:

<#@ import namespace="Microsoft.CSharp"#>
<#@ import namespace="System.Text"#>


public class CustomUtilities
{
    public static string EntityNameToSqlName(string name)
    {
        string sqlName = "";    // The table name based on the input model name
        string pattern = "([A-Z]+[s])|([A-Z](?=[a-z]))|((?<=[a-z])[A-Z])";  //Pattern for the regex exp. below

        // Separate out each word with spaces:
        sqlName = System.Text.RegularExpressions.Regex.Replace(name, pattern, " $&");

        // Replace spaces with underscores and then make lowercase:
        sqlName = sqlName.Trim().Replace(" ", "_").ToLower();

        return sqlName;
    }

}

Я попытался сослаться на этот файл в моем собственном файле генерации DDL в верхней части страницы следующим образом:

<#@ include file="MyOrg.EF.Utility.CS.ttinclude"#>

Однако, если я попытаюсь сослаться на вышеуказанную функцию, используя код, подобный этому, в файле .tt:

string tableName = CustomUtilities.EntityNameToSqlName(Id(entitySet.GetTableName()));

Затем Visual Studio жалуется, что Имя 'CustomUtilities' не существует в текущем контексте . Удаление имени класса из «CustomUtilities.EntityNameToSqlName» возвращает похожую ошибку. Стоит ли попробовать другой способ вставить пользовательскую функцию в код генерации DDL?

Окончательное решение:

Мне удалось наконец заставить это работать после того, как я понял, что я не обернул код C # в моем MyOrg.EF.Utility.CS.ttinclude файле с этим:

<#+
[my code]
#>

Мне также нужно было добавить публичную копию метода WriteColumns () , найденного в файле GenerateTSQL.Utility , чтобы он использовал мой метод EntityNametoSqlName ().

К сожалению, моя настроенная версия оригинального SSDLToSQL10.tt теперь немного грязная, так как мне нужно обернуть CustomUtilities.EntityNameToSqlName () вокруг довольно многих элементов. ,

Ответы [ 3 ]

4 голосов
/ 07 октября 2013

Правильное решение - изменить соглашение об именах баз данных.

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

Целью соглашения об именах является снижение сложности. Тем не менее, здесь принято решение реализовать все виды дополнительной сложности. И любой другой ORM должен был бы придумать свое запутанное решение этой искусственной проблемы.

2 голосов
/ 14 июля 2011

Конечно, есть. Существует шаблон T4, который преобразует вашу модель в сценарии SQL DDL. Вы можете сделать копию этого шаблона и поместить свою собственную логику для генерации имени в новую копию. После этого вам просто нужно установить этот шаблон в конструкторе (свойство Шаблон генерации DDL) и запустить Создать базу данных из модели ...

Шаблон по умолчанию вы найдете в:

%VSINSTALLDIR%\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
0 голосов
/ 13 июля 2011

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

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
     modelBuilder.Entity<EntityName>().Map(c => c.ToTable("TableName"));//to map entity with table
     modelBuilder.Entity<EntityName>().Property(s => s.Property).HasColumnName("ColomnName");//to map properties with colomns
}
...