我在更新實體框架實體中的外鍵時遇到問題。我正在使用自我跟蹤實體,並且有一個具有某些關係的實體,其中外鍵也作爲屬性存在(EF4的新功能之一)。鍵(整數)被標記爲可空和併發模式固定。實體框架4中允許可空的外鍵?
具體來說,我有一個與確認用戶有很多到0..1關係的警報實體。 (用戶可以確認多個警報,但只有零個或一個用戶可以確認警報)。
實體定義(簡體):
Alarm properties
Id Int32 non-nullable identity entity key
UserId Int32 nullable concurrency mode fixed
Alarm navigation properties
User 0..1 multiplicity
User properties
Id Int32 non-nullable identity entity key
Name String non-nullable
在我的自我跟蹤實體確認用戶ID是自動生成的,就像預期可空,但是如果我將用戶分配到一個已經持續報警運行ApplyChanges,自我跟蹤上下文擴展嘗試在EF上下文中設置原始值(空值)(在上下文擴展中的SetValue中),但由於EdmType的ClrEquivalentType是不可空的Int32而靜默跳過。
自動生成的擴展代碼:
private static void SetValue(this OriginalValueRecord record, EdmProperty edmProperty, object value)
{
if (value == null)
{
Type entityClrType = ((PrimitiveType)edmProperty.TypeUsage.EdmType).ClrEquivalentType;
if (entityClrType.IsValueType &&
!(entityClrType.IsGenericType && typeof(Nullable<>) == entityClrType.GetGenericTypeDefinition()))
{
// Skip setting null original values on non-nullable CLR types because the ObjectStateEntry won't allow this
return;
}
}
int ordinal = record.GetOrdinal(edmProperty.Name);
record.SetValue(ordinal, value);
}
當EF稍後嘗試更新我報警,我得到一個OptimisticConcurrencyException因爲它構建在它使用0(零)作爲原始的UPDATE語句的WHERE子句用戶外鍵值而不是正確的「爲空」。 (WHERE子句是EF樂觀併發機制的一部分,其中用「固定」併發模式標記的屬性的原始值再次被檢查數據庫中的屬性)。
EF的自我跟蹤實體中是否完全不支持可爲空的外鍵/基元類型? 如果沒有,我是否被迫使用虛擬實體而不是null或者是否有其他解決方法?
更新 我試圖重現該問題不STE,但普通的EF似乎處理樂觀併發以及對空的外鍵,所以這是一個STE的問題,而不是一個EF問題。 自我跟蹤實體存在很多問題,所以這裏出現故障並不奇怪。如果我找到可以在STE T4腳本中實施的解決方法,我會在此處發佈它。
我很確定我的主鍵是確定的。 當我將可空引用實體更改爲新實體時,會發生此問題。這會導致原始實體引用(null)和密鑰(null)被存儲在原始值集合中。 當調用ApplyChanges時,嘗試將原始值從實體更改跟蹤器移至EF上下文,但由於EF上下文將密鑰的類型定義爲Int32,而非Nullable作爲自跟蹤實體,因此無法將其指定爲null 。 –
Holstebroe
2010-08-31 07:28:56
可空列int列應該在你的CSDL中作爲int?'而不是'int'。嘗試使用新的(以前未映射的)表;你會看到的。自從創建模型後,你是否改變了可空性? – 2010-08-31 12:43:41
我試圖創建一個新的實體「FooEntity」,沒有主鍵和一個名爲Foo的可空Int32。這是在CSDL產生: <的EntityType名稱= 「FooEntity」> <物業類型= 「的Int32」 NAME = 「富」 可空= 「真」/> 沒有的Int32?這裏。將Int32更改爲Int32?導致錯誤「值'Int32?'根據其數據類型'http://schemas.microsoft.com/ado/2008/09/edm:TPropertyType' – Holstebroe 2010-09-01 06:34:59