2

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

我总是会遇到以下方面的异常:

无法将“MyRecord”上的“SortOrder”属性设置为“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将被抛出:

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

也许一旦 DbSet 接收到表达式,就可以透明地重写它?我很想知道这是否可行;我对表达树不够熟练。到目前为止,我未能在 DbSet 中找到一个可以重写以操纵表达式的方法,但我并没有超越创建一个实现 IDbSet 并传递给 DbSet 的新类,尽管那会很可怕。

在调查堆栈跟踪时,我发现了一个对称为 Shaper 的内部实体框架概念的引用,它似乎是获取数据并将其输入的东西System.Data.Entity.dll 与 dotPeek 表明这肯定会帮助我......假设Shaper<T>不是内部和密封的。我几乎可以肯定在这里吠错了树,但我很想知道是否有人以前遇到过这种情况。

4

1 回答 1

1

这是一个相当难以破解的难题,但您可以通过Microsoft.Linq.Translations做到这一点。

于 2012-04-26T17:50:01.923 回答