实体框架——解决EF4中实体与我们的数据库标准之间的命名约定冲突



我正在研究用实体框架4替换或补充我们自己开发的ORM系统,我注意到后者可能最终导致我们为编程代码和数据库定义的命名约定之间的冲突。作为一家微软公司,我们很大程度上决定遵循微软的代码命名准则,即成员、命名空间等使用Pascal大小写;为了避免使用下划线,等等

EF4中的默认实体命名约定与这些标准配合得很好,这并不奇怪。例如,一个名为SalesOrder的实体将生成一个名为SalesOrder的类和一个名为SalesOrders的实体集。缺省情况下,EF4 Model-First设计将生成一个与实体集同名的表(在本例中,生成的表名为SalesOrders)。然而,我们的数据库标准建议在单词之间使用所有小写和下划线(例如,sales_orders)。因此,"按原样"使用实体框架将导致我们开始偏离它们。

是否有任何地方在实体框架,你可以覆盖它的行为使用实体集名称作为SQL表名称?我似乎找不到一个明显的地方来为生成的SQL脚本指定另一个表名。如果我们继续使用EF4,唯一可行的解决方案是让我们重新考虑数据库命名约定吗?

更新:

我在下面尝试Ladislav的解决方案,但我似乎无法在实体框架模型设计器中获得从模型生成数据库选项来识别我的自定义实用程序。我有一个名为MyOrg.EF.Utility.CS的文件。目录:

%VSINSTALLDIR%Common7IDEExtensionsMicrosoftEntity Framework ToolsTemplatesIncludes

它实际上是这样的:

<#@ 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;
    }
}

我尝试在顶部附近的自定义.tt 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。包含文件

<#+
[my code]
#>

我还需要添加在GenerateTSQL文件中找到的WriteColumns()方法的公共副本。实用程序,以便它将使用我的EntityNametoSqlName()方法。

不幸的是,我的自定义版本的原始SSDLToSQL10。tt文件现在有点乱,因为我需要包装CustomUtilities.EntityNameToSqlName()周围有相当多的项目在那里。

正确的解决方案是更改数据库命名约定。

为什么本末倒置?在现代编程中,大多数操作发生在高度可伸缩的业务/服务层,而不是数据库。程序员应该使用一种同时适用于这两种对象的命名约定——它应该满足应用程序开发人员的需求,因为他们将每天使用这些对象。在某些情况下,它可能应该满足前端开发人员的需求,在其他情况下,服务器端。

命名约定的全部目的是降低复杂性。然而,这里公认的解决方案是实现各种额外的复杂性。每个其他ORM都必须想出他们自己复杂的解决方案来解决这个人为的问题。

当然有。有T4模板,它将您的模型转换为SQL DDL脚本。您可以创建此模板的副本,并将自己的名称生成逻辑放入新副本中。之后,您只需要在设计器中设置此模板(DDL生成模板属性)并运行从模型生成数据库…

你会发现默认模板在:

%VSINSTALLDIR%Common7IDEExtensionsMicrosoftEntity Framework ToolsDBGenSSDLToSQL10.tt

你可以的。您需要实现一个自定义模型构建器,将实体与相关表和相关列进行映射。您可以通过将OnModelCreating函数添加到您的上下文类中来覆盖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
}

最新更新