私は現在、Entity Framework アプリケーションを、約 10 年前のレガシー データベースと統合しようとしています。このデータベースが持つ多くの問題の 1 つは (リレーションや制約がまったくないことに加えて)、ほぼすべての列が null に設定されていることです。ただし、ほとんどの場合、これは意味がありません。
例外なく、次の行に沿って例外が発生します。
「MyRecord」の「SortOrder」プロパティを「null」値に設定できませんでした。このプロパティは、'Int32' 型の null 以外の値に設定する必要があります。
上記の例外に言及する多くの質問を見てきましたが、これらはすべて、開発者がデータベース内のデータを適切に表すクラスを作成しなかったという本当の間違いのようです。データベース内のデータを適切に表現しないクラスを意図的に作成したいと考えています。これが Entity Framework の規則に違反していることを十分に認識しており、それがおそらく私がそれを行うのに非常に苦労している理由です。
既存のアプリケーションが破損するため、この時点でスキーマを変更することはできません。古いアプリケーションによって新しいデータが挿入されるため、データを修正することもできません。データベースを本来の Entity Framework にマップし、最終的にデータベースの再設計フェーズに移行できるようになる前に、データ アクセスに依存するように、すべてのアプリケーションを今後数年かけてゆっくりと移動させたいと考えています。
これを回避するために私が使用した方法の 1 つは、変数を透過的にプロキシすることです。
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 と呼ばれる内部の Entity Framework 概念への参照を見つけました。これは、データを取得して入力するものであると思われます。 System.Data.Entity.dll with dotPeek は、これが確かに私を助けるものであることを示しています...Shaper<T>
内部および封印されていないと仮定します。ここで間違ったツリーを吠えていることはほぼ確実ですが、これまでに誰かがこれに遭遇したことがあるかどうか聞いてみたいです.