我在更新Entity Framework实体中的外键时遇到问题。我正在使用自我跟踪实体并且具有一些具有某种关系的实体,其中外键也作为属性存在(EF4的新特征之一)。密钥(整数)标记为Nullable和并发模式已修复。
具体来说,我有一个与确认用户有很多到0..1关系的Alarm实体。 (用户可以确认多个警报,但只能由零个或一个用户确认警报。)
实体定义(简化):
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会像预期的那样自动生成为Nullable,但是如果我将用户分配给已经存在的警报并运行ApplyChanges,则自我跟踪上下文扩展会尝试设置原始值( null)在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,因为它在UPDATE语句中构造一个WHERE子句,它使用0(零)作为原始用户外键值而不是正确的“is null”。 (WHERE子句是EF乐观并发机制的一部分,其中标记为“固定”并发模式的属性的原始值将再次检查数据库中的属性。)
EF的自我跟踪实体是否完全支持可为空的外键/原始类型? 如果没有,我是否被迫使用虚拟实体而不是null或是否有其他解决方法?
更新 我试图在没有STE的情况下重现这个问题,但普通的EF似乎很好地处理了可以为空的外键的乐观并发,所以这是一个STE问题,而不是EF问题。 自跟踪实体存在许多问题,因此这里存在故障并不奇怪。如果我找到可以在STE T4脚本中实现的解决方法,我将在此处发布。
答案 0 :(得分:1)
答案 1 :(得分:0)
是的,肯定允许可以为空的外键。我们到处都用它们。您没有显示您的数据库或模型,因此很难确定问题是什么,但听起来好像实体框架无法找出其中一个表的主键。也许你没有一个,也许是因为其中一个是观点?我在这里猜测,因为你没有提供有关你正在做什么的大量信息。