我有一个在Entity Framework实体中更新外键的问题。我使用自跟踪实体,并且有一个带有一些关系的实体,其中外键也作为属性存在(EF4的新功能之一)。该键(一个整数)被标记为可为空和并发模式固定。
具体来说,我有一个警报实体与确认用户之间的多对0..1关系。(一个用户可以确认多个警报,但一个警报只能被零或一个用户确认)。
实体定义(简化):
在我的自我跟踪实体中,确认用户ID被自动生成为可为空的,这正如预期的那样。然而,如果我将用户分配给已经持久化的警报并运行ApplyChanges,则自我跟踪上下文扩展会尝试在EF上下文中设置原始值(null)(在上下文扩展的SetValue中),但由于EdmType的ClrEquivalentType是不可为空的Int32,它会默默地跳过该操作。
自动生成的扩展代码:
当EF尝试更新我的警报时,我会收到一个OptimisticConcurrencyException,因为它在UPDATE语句中构造了一个WHERE子句,其中使用0(零)作为原始用户外键值,而不是正确的“is null”。 (WHERE子句是EF乐观并发机制的一部分,在此机制中,标记为“fixed”并发模式的属性的原始值将与数据库中的属性再次进行检查)。
在EF的自跟踪实体中,可空外键/基元类型是否得到充分支持?
如果没有,则必须使用虚拟实体代替null,或者是否有其他解决方法?
更新 我已尝试使用非STE重现问题,但是普通EF似乎可以很好地处理可空外键的乐观并发,因此这是一个STE问题,而不是EF问题。 自跟踪实体存在许多问题,因此在此处出现故障并不奇怪。如果我找到可以在STE T4脚本中实现的解决方法,我将在此发布。
具体来说,我有一个警报实体与确认用户之间的多对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上下文中设置原始值(null)(在上下文扩展的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,因为它在UPDATE语句中构造了一个WHERE子句,其中使用0(零)作为原始用户外键值,而不是正确的“is null”。 (WHERE子句是EF乐观并发机制的一部分,在此机制中,标记为“fixed”并发模式的属性的原始值将与数据库中的属性再次进行检查)。
在EF的自跟踪实体中,可空外键/基元类型是否得到充分支持?
如果没有,则必须使用虚拟实体代替null,或者是否有其他解决方法?
更新 我已尝试使用非STE重现问题,但是普通EF似乎可以很好地处理可空外键的乐观并发,因此这是一个STE问题,而不是EF问题。 自跟踪实体存在许多问题,因此在此处出现故障并不奇怪。如果我找到可以在STE T4脚本中实现的解决方法,我将在此发布。
int?
,而不是int
。尝试使用一个新的(之前未映射的)表格;你会看到区别的。自从你创建模型以来,你改变了 nullability 吗? - Craig Stuntzint?
。固定并发可能不适用于随机FK;我们使用TIMESTAMP
字段来解决此问题。 - Craig Stuntz