在Entity Framework中透明地将可空值转换为不可为空的值

时间:2012-04-26 14:46:35

标签: entity-framework expression-trees entity-framework-ctp5

我目前正在尝试将Entity Framework应用程序与大约十年左右的旧数据库集成。这个数据库存在的许多问题之一(除了没有任何关系或约束)几乎每列都设置为空,即使在几乎所有情况下,这都没有意义。

我总是会遇到这样的例外情况:

  

' SortOrder'物业在' MyRecord'无法设置为' null'值。您必须将此属性设置为类型为' Int32'。

的非空值

我看过许多引用上述异常的问题,但这些似乎都是真正的错误,开发人员没有编写能够正确表示数据库中数据的类。我想故意编写一个不能正确表示数据库中数据的类。我完全清楚这违反了实体框架的规则,这很可能是我为什么要这么做的原因。

此时无法更改架构,因为它会破坏现有应用程序。也无法修复数据,因为旧数据库将插入新数据。我想用实体框架映射数据库,在接下来的几年左右慢慢移动所有应用程序,以便在最终能够进入数据库重新设计阶段之前依赖它来进行数据访问。

我用来解决这个问题的一个方法是透明地代理变量:

internal int? SortOrderInternal { get; set; }

public int SortOrder
{
    get { return this.SortOrderInternal ?? 0; }
    set { this.SortOrderInternal = value; }
}

然后我可以在CodeFirst中映射字段:

entity.Ignore(model => model.SortOrder);
entity.Property(model => model.SortOrderInternal).HasColumnName("SortOrder");

在这种方法中使用internal关键字可以很好地封装这种肮脏,所以我至少可以防止它泄漏到我的数据访问程序集之外。

但遗憾的是,我现在无法在查询中使用代理字段,因为NotSupportedException将被抛出:

  

指定的类型成员' SortOrder' LINQ to Entities不支持。仅支持初始化程序,实体成员和实体导航属性。

也许有可能在DbSet收到表达式后透明地重写表达式?我很想知道这是否有效;我对表达树说不够熟练。到目前为止,我没有成功找到DbSet中的一个方法,我可以覆盖它来操作表达式,但我不是要创建一个实现IDbSet并传递给DbSet的新类,尽管这样会很糟糕。

在调查堆栈跟踪时,我发现了对一个名为Shaper的内部实体框架概念的引用,它似乎是将数据输入到这个概念的谷歌搜索的一小部分。产生任何东西,但用dotPeek调查System.Data.Entity.dll表明这肯定会对我有所帮助......假设Shaper<T>没有内部和密封。我几乎肯定会在这里咆哮错误的树,但是我有兴趣听听以前是否有人遇到过这个。

1 个答案:

答案 0 :(得分:1)

这是一个相当难以破解的难题,但您可以通过Microsoft.Linq.Translations来完成。