Разрешить конфликт соглашения об именах между сущностями в EF4 и стандартами нашей базы данных?
Я расследую вопрос о замене или дополнении нашей собственной системы 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.TT вверху как таковой:
<#@ 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 ответа
Конечно, есть. Существует шаблон T4, который преобразует вашу модель в сценарии SQL DDL. Вы можете сделать копию этого шаблона и добавить свою собственную логику для генерации имени в новую копию. После этого вам просто нужно установить этот шаблон в конструкторе (свойство шаблона генерации DDL) и запустить Generate Database from Model ...
Вы найдете шаблон по умолчанию в:
%VSINSTALLDIR%\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
Правильное решение - изменить соглашение об именах баз данных.
Почему хвост должен вилять собакой? В современном программировании большинство действий происходит на высокомасштабируемом уровне бизнес / сервисов, а не на базе данных. Программисты должны использовать соглашение об именах, которое работает для обоих - и должно отвечать потребностям разработчика приложений, который будет работать с этими объектами изо дня в день. В некоторых случаях это, вероятно, должно отвечать потребностям разработчика интерфейса, в других - на стороне сервера.
Вся цель соглашения об именах состоит в том, чтобы уменьшить сложность. Тем не менее, принятым решением здесь является реализация всех видов дополнительной сложности. И любой другой ORM должен был бы придумать свое запутанное решение этой искусственной проблемы.
Ты можешь это сделать. Вам необходимо реализовать собственный построитель моделей для сопоставления ваших сущностей с соответствующими таблицами и соответствующими столбцами. Вы можете переопределить функцию 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
}