EF Code First - 全局设置nvarchar上的varchar映射

Vul*_*ary 16 c# code-first entity-framework-4 ef-code-first

我有一个简单的问题,但我自己无法找到答案.

我正在使用EF4 CTP-5 Code First Model和手工生成的POCO.它正在处理生成的SQL中的字符串比较

WHERE N'Value' = Object.Property
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用以下方法覆盖此功能:

[Column(TypeName = "varchar")]
public string Property {get;set;}
Run Code Online (Sandbox Code Playgroud)

这解决了该单个事件的问题并正确生成SQL为:

WHERE 'Value' = Object.Property
Run Code Online (Sandbox Code Playgroud)

但是,我正在处理一个非常大的域模型并遍历每个字符串字段并设置TypeName ="varchar"将非常非常繁琐.我想指定EF应该在整个板上看到字符串为varchar,因为这是该数据库中的标准,nvarchar是例外情况.

想要纠正这个问题的推理是查询执行效率.varchar和nvarchar之间的比较在SQL Server 2k5中非常低效,其中varchar到varchar比较几乎立即执行.

Die*_*hon 9

在EF 4.1之前,您可以使用约定并将以下约定添加到ModelBuilder:

using System;
using System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive;
using System.Data.Entity.ModelConfiguration.Conventions.Configuration;
using System.Reflection;

public class MakeAllStringsNonUnicode :
    IConfigurationConvention<PropertyInfo, StringPropertyConfiguration>
{
    public void Apply(PropertyInfo propertyInfo, 
                      Func<StringPropertyConfiguration> configuration)
    {
        configuration().IsUnicode = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

(摘自http://blogs.msdn.com/b/adonet/archive/2011/01/10/ef-feature-ctp5-pluggable-conventions.aspx)


更新:4.1版本的可插入约定已被删除.查看我的博客以寻找替代方法)


RMD*_*RMD 5

对于任何希望在 EF Core(v3 及更高版本)中执行此操作的人来说,实现此目的的快速方法是通过属性ModelBuilder.Model;它可以轻松访问模型中的所有实体和属性。

“简单”的实现如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Apply configurations via regular modelBuilder code-first calls
    // ... 
    // ...


    // Override the configurations to force Unicode to false
    var entities = modelBuilder.Model.GetEntityTypes();
    foreach (var entity in entities)
    {
        foreach (var property in entity.GetProperties())
        {
            property.SetIsUnicode(false);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

EF Core 很高兴地忽略SetIsUnicode对非字符串属性的调用,因此您甚至不必检查属性类型(但如果这让您感觉更好的话,您可以轻松检查:)

对于那些喜欢更明确一点的人来说,在调用中添加一个 where 子句GetProperties()就可以解决问题:

...
    var stringProperties = entity.GetProperties()
                                 .Where(e=> e.ClrType == typeof(string));
    foreach (var property in stringProperties)
    {
       property.SetIsUnicode(false);
    }
...
Run Code Online (Sandbox Code Playgroud)

更新 - 实体框架核心 6

您现在可以使用 EF Core 6 的预约定模型配置来执行此类开箱即用的全局映射

下面显示了如何使用此新功能实现此目的的示例:

configurationBuilder
    .DefaultTypeMapping<string>()
    .IsUnicode(false);
Run Code Online (Sandbox Code Playgroud)