首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >EF Code First -在nvarchar上全局设置varchar映射

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

Stack Overflow用户
提问于 2011-02-25 02:58:11
回答 3查看 10.9K关注 0票数 17

我有一个本应很简单的问题,但我自己一直找不到答案。

我正在使用EF4 CTP-5代码第一模型与手动生成的POCOs。它将生成的SQL中的字符串比较处理为

代码语言:javascript
复制
WHERE N'Value' = Object.Property

我知道我可以使用以下命令覆盖此功能:

代码语言:javascript
复制
[Column(TypeName = "varchar")]
public string Property {get;set;}

它修复了该单次出现的问题,并将SQL正确生成为:

代码语言:javascript
复制
WHERE 'Value' = Object.Property

然而,我正在处理一个非常大的域模型,遍历每个字符串字段并设置TypeName = "varchar“将是非常非常繁琐的。我想指定EF应将字符串视为全面的varchar,因为这是此数据库中的标准,而nvarchar是例外情况。

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

EN

回答 3

Stack Overflow用户

发布于 2012-09-11 02:00:34

我扩展了Marc Cals的答案(和Diego的博客文章),根据问题将所有实体上的所有字符串全局设置为非unicode,而不是必须按类手动调用。见下文。

代码语言:javascript
复制
/// <summary>
/// Change the "default" of all string properties for a given entity to varchar instead of nvarchar.
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="entityType"></param>
protected void SetAllStringPropertiesAsNonUnicode(
    DbModelBuilder modelBuilder,
    Type entityType)
{
    var stringProperties = entityType.GetProperties().Where(
        c => c.PropertyType == typeof(string)
           && c.PropertyType.IsPublic 
           && c.CanWrite
           && !Attribute.IsDefined(c, typeof(NotMappedAttribute)));

    foreach (PropertyInfo propertyInfo in stringProperties)
    {
        dynamic propertyExpression = GetPropertyExpression(propertyInfo);

        MethodInfo entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
        MethodInfo genericEntityMethod = entityMethod.MakeGenericMethod(entityType);
        object entityTypeConfiguration = genericEntityMethod.Invoke(modelBuilder, null);

        MethodInfo propertyMethod = entityTypeConfiguration.GetType().GetMethod(
            "Property", new Type[] { propertyExpression.GetType() });

        StringPropertyConfiguration property = (StringPropertyConfiguration)propertyMethod.Invoke(
            entityTypeConfiguration, new object[] { propertyExpression });
        property.IsUnicode(false);
    }
}

private static LambdaExpression GetPropertyExpression(PropertyInfo propertyInfo)
{
    var parameter = Expression.Parameter(propertyInfo.ReflectedType);
    return Expression.Lambda(Expression.Property(parameter, propertyInfo), parameter);
}

/// <summary>
/// Return an enumerable of all DbSet entity types in "this" context.
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
private IEnumerable<Type> GetEntityTypes()
{
    return this
        .GetType().GetProperties()
        .Where(a => a.CanWrite && a.PropertyType.IsGenericType && a.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
        .Select(a => a.PropertyType.GetGenericArguments().Single());
}

最后,从您的OnModelCreating(DbModelBuilder ModelBuilder)调用它:

代码语言:javascript
复制
foreach (var entityType in GetEntityTypes())
    SetAllStringPropertiesAsNonUnicode(modelBuilder, entityType);
票数 4
EN

Stack Overflow用户

发布于 2012-04-30 05:58:36

在Diego的博客帮助下,在不使用anotations的情况下创建POCO varchar的公共属性是:

代码语言:javascript
复制
    private void SetStringPropertiesAsNonUnicode<e>(DbModelBuilder _modelBuilder) where e:class
    {
        //Indiquem a totes les propietats string que no són unicode per a que es crein com a varchar
        List<PropertyInfo> stringProperties = typeof(e).GetProperties().Where(c => c.PropertyType == typeof(string) && c.PropertyType.IsPublic).ToList();
        foreach (PropertyInfo propertyInfo in stringProperties)
        {
            dynamic propertyExpression = GetPropertyExpression(propertyInfo);
            _modelBuilder.Entity<e>().Property(propertyExpression).IsUnicode(false);
        }
    }

    // Edit: Also stole this from referenced blog post (Scott)
    static LambdaExpression GetPropertyExpression(PropertyInfo propertyInfo)
    {
       var parameter = Expression.Parameter(propertyInfo.ReflectedType);
       return Expression.Lambda(Expression.Property(parameter, propertyInfo), parameter);
    }
票数 1
EN

Stack Overflow用户

发布于 2021-05-18 03:38:30

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

下面是一个“基本”实现:

代码语言:javascript
复制
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);
        }
    }
}

EF Core愉快地忽略了对非字符串属性的SetIsUnicode调用,因此您甚至不必检查属性类型(但如果它让您感觉更好的话,您可以很容易地这样做:)

对于那些想要更明确一点的人来说,在GetProperties()调用中添加where子句可以做到这一点:

代码语言:javascript
复制
...
    var stringProperties = entity.GetProperties()
                                 .Where(e=> e.ClrType == typeof(string));
    foreach (var property in stringProperties)
    {
       property.SetIsUnicode(false);
    }
...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5109170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档