如何重写查询表达式以使用int替换枚举?

时间:2011-03-19 13:47:53

标签: c# entity-framework reflection expression-trees entity-framework-4.1

受到希望能够在EF查询中使用枚举的启发,我正在考虑将ExpressionVisitor添加到我的存储库中,这些存储库将采用传入的条件/规范标准并重写它们以使用相应的持久性int属性。

我一直在我的(代码优先)实体中使用以下值后缀模式:

public class User : IEntity
{
    public long ID { get; set; }

    internal int MemberStatusValue { get; set; }

    public MemberStatus MemberStatus 
    {
        get { return (MemberStatus) MemberStatusValue; }
        set { MemberStatusValue = (int) value; }
    }
}

使用以下内容将其映射到数据库:

internal class UserMapping : AbstractMappingProvider<User>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        // adds ToTable and other general mappings
        base.DefineModel( modelBuilder );

        Map.Property( e => e.MemberStatusValue ).HasColumnName( "MemberStatus" );
    }
}

在我的存储库中,我有以下方法:

public IQueryable<T> Query( Expression<Func<T, bool>> filter, params string[] children )
{
    if( children == null || children.Length == 0 )
    {
        return Objects.Where( filter );
    }
    DbQuery<T> query = children.Aggregate<string, DbQuery<T>>( Objects, ( current, child ) => current.Include( child ) );
    return filter != null ? query.Where( filter ) : query;
}

我想在此方法中添加一个方法调用来重写过滤器表达式,用对MemberStatusValue的引用替换对MemberStatus属性的所有引用。

我想这将是一个涉及到in this SO post之类的解决方案,但我不确定如何从想法到实现。

如果您可以就添加此功能可能对性能产生影响提供任何建议,我们也将不胜感激。

1 个答案:

答案 0 :(得分:1)

我不确定这是否是您所追求的,但我发现以类似但稍微不同的方式处理枚举更简单。也就是说,我有两个属性,但我的int属性是公共的,是数据库持久存在的;然后我有另一个公共的“包装器”属性,它通过从/到所需枚举类型的强制转换获取/设置int属性值,这是应用程序其余部分实际使用的。

因此,我不必乱用该模型; EF理解并持久化int属性,而应用程序的其余部分与枚举类型进行良好的交互。关于我的方法,我唯一不喜欢的是我必须在任何枚举值上编写我的LINQ语句,并尝试查询将其转换为int以匹配实际持久化的字段。然而,这是一个很小的代价,我想向你推荐,因为在我看来,你正在使用一个字符串来生成你的查询,它放弃了LINQ提供的所有类型安全性,Intellisense等。 / p>

最后,如果您对如何使用EF 5中的新枚举功能感兴趣(如果您想试用它,现在可以在测试版中下载),请查看以下内容:

http://msdn.microsoft.com/en-us/hh859576