实体框架4中是否允许可以为空的外键?

Hol*_*roe 7 entity-framework nullable optimistic-concurrency self-tracking-entities

我在更新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
Run Code Online (Sandbox Code Playgroud)

在我的自我跟踪实体中,确认用户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);
    }
Run Code Online (Sandbox Code Playgroud)

当EF稍后尝试更新我的警报时,我得到一个OptimisticConcurrencyException,因为它在UPDATE语句中构造一个WHERE子句,它使用0(零)作为原始用户外键值而不是正确的"is null".(WHERE子句是EF乐观并发机制的一部分,其中标记为"固定"并发模式的属性的原始值将再次检查数据库中的属性).

EF的自我跟踪实体是否完全支持可空的外键/原始类型?如果没有,我是否被迫使用虚拟实体而不是null或是否有其他解决方法?

更新 我试图在没有STE的情况下重现问题,但普通EF似乎很好地处理可以为空的外键的乐观并发,所以这是一个STE问题,而不是EF问题.自跟踪实体存在许多问题,因此这里存在故障并不奇怪.如果我找到可以在STE T4脚本中实现的解决方法,我将在此处发布.

Hol*_*roe 1

Bill Huth 在MSDN上发布了一个工作补丁。