我目前正在嘗試將實體框架應用程序與大約十年左右的舊數據庫集成。這個數據庫存在的許多問題之一(除了沒有關係或約束之外)幾乎每一列都被設置爲空,即使在幾乎所有情況下,這都是沒有意義的。在實體框架中將可空值透明地轉換爲不可空值
不變的是,我會遇到一個異常沿着這些線路:
上「MyRecord」的「SortOrder的」屬性不能被設置爲「空」值。您必須將此屬性設置爲「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到實體。僅支持初始化程序,實體成員和實體導航屬性。
也許它可能會透明地重寫表達式,一旦它被DbSet接收到了?我很想知道這是否會起作用。表達樹說我不夠熟練。到目前爲止,我在DbSet中找不到一個可以重寫的方法來操作表達式,但我並沒有在上面創建一個實現IDbSet並傳遞給DbSet的新類,儘管這很可怕。
在調查堆棧跟蹤時,我發現了一個名爲Shaper的內部實體框架概念的引用,這個概念似乎是將數據輸入並輸入到它的東西的一個小技巧。任何事情,但用dotPeek調查System.Data.Entity.dll表明,這肯定會幫助我......假設Shaper<T>
不是內部和密封。我幾乎肯定會在這裏咆哮錯誤的樹,但我有興趣知道是否有人以前遇到過這種情況。
是否有你不想使用可空屬性的原因?感覺有點像你試圖「對抗」數據庫模式,而不是接受它的限制並相應地編寫你的代碼。 – 2012-04-26 14:55:08
出於興趣,爲什麼不在CSDL /模型屬性中使實體屬性爲null = false?雖然底層的SSDL可以爲空,但它會正確映射非空值,但是如果數據庫中有空值,您需要處理ConstraintException(yyy上的XXX屬性不能設置爲空屬性) – StuartLC 2012-04-26 15:03:00
@ AndrewStephens我不想這樣做,因爲它不是應該如何設計數據庫。例如,還有一種情況是兩個不同的實體存儲在我使用實體框架解決的同一個表中。我想重新解釋應用程序層中的數據,然後在將來修復數據庫。如果我在實體框架圖層的類中允許可爲空的值(並且它實際上幾乎是每個字段,即使是外鍵),我都沒有真正解決這個問題。 – 2012-04-26 15:12:46