我有一個實體框架4設計,允許在不修改指向它們的實體的情況下刪除引用表(無級聯刪除)。因此,例如實體A在ID字段中具有對實體B的外鍵引用。 B可以被刪除(並且數據庫中沒有FK約束來阻止),所以如果我查看ABID,它總是一個有效的字段(因爲所有這些都會返回A中的ID字段),即使沒有由於前一次刪除而使用該ID記錄B.這是通過設計,我不想級聯刪除,我需要A記錄堅持一段時間用於審計目的。EF4:篩選出不存在的引用實體
問題是過濾不存在的已刪除記錄並不像聽起來那麼容易。因此,舉例來說,如果我這樣做:
from c in A
select A.B.somefield;
這導致OUTER JOIN在生成的SQL,所以它拿起,即使他們是指缺少乙記錄的所有A記錄。所以,我一直用來解決這個問題(因爲我找不到更好的方法!)是添加一個where子句來檢查引用的B記錄中的字符串字段。如果B實體中的該字段爲空,那麼我假設B不存在。
from c in A
where c.B.somestringfield != null
select A.B.somefield;
似乎工作如果B.somestringfield是一個字符串。如果它是一個整數,這是行不通的!
這對我來說都是這樣。我想到了一些解決方案,但它們並不實用:
- 查詢刪除B時刪除B並刪除其外鍵的所有引用B的表。這非常難看,如果我在將來添加另一個引用B的實體,我不想記住這麼做。更何況一個巨大的性能延遲解決所有的引用,每當我刪除的東西。
- 將字符串字段添加到每個表,我可以指望在那裏,我可以檢查實體是否存在。 Blech,我不想爲此添加數據庫字段。
- 實施軟刪除並保持所有參考完整性 - 基本上設置了級聯刪除,但是這將導致巨大的數據庫膨脹,因爲由於引用而無法清除大量記錄。不行。
我原本以爲這個問題與舔了舔「檢查中引用的實體某個字段爲空」的把戲,但我不完全理解的條件(如果我沒有什麼任何條件下打破?在引用表什麼樣的領域將工作整數不會)
舉個例子,如果我在實體B的整場「數」和我檢查,看它是否爲null,如:?
from c in A
where c.B.count != null
select c.B.count;
我得到一堆記錄與計數混合在結果爲空的記錄,事實上查詢炸彈與一個「InvalidOperationException:由於物化值爲null,因此值類型轉換爲'Int32'失敗。無論是結果型的泛型參數或查詢必須使用可空類型。」
所以我需要做的
from c in A
where c.B.count != null
select new { count = (int?)c.B.count };
,甚至看空的記錄。所以,這是非常令人費解對我怎麼說查詢可以結果完全沒有結果。
我剛剛發現的東西,如果我做一個明確加入這樣的,SQL是INNER JOIN,一切的偉大工程:
from c in A
join j in B on A.B.ID equals j.ID
select c;
但這很爛。我將不得不修改大量查詢來添加顯式連接子句,而不是享受與EF獲得的關係字段的便利性。有點擊敗了目的,並增加了更多的代碼維護。
謝謝你,這是非常有用的信息。我沒有真正理解可選與必需的導航屬性,但它確實有意義,如果它只是映射到FK約束。在我的情況下,我完全同意我只是憎恨破壞必要的語義意義,因爲它不在設計之中,如果它引起可能出人意料的怪異行爲,就忘記它。在我看來,最好的方式是使用顯式的LINQ連接來修改某些查詢,以強制生成INNER JOIN並在這些情況下獲得正確的結果。謝謝! –