Допускаются ли внешние ключи, допускающие значение NULL, в Entity Framework 4?

У меня проблема с обновлением внешнего ключа в сущности Entity Framework. Я использую самотслеживание сущности и имеют сущность с некоторыми отношениями, в которых внешний ключ также присутствует как свойство (одна из новых функций EF4). Ключ (целое число) помечен как Nullable, а режим параллелизма исправлен.

В частности, у меня есть Тревожный объект со многими до 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

В моей сущности с самотслеживанием подтверждающий идентификатор пользователя автоматически генерируется как Имеет значение Nullable, как и ожидалось, однако, если я назначаю пользователю уже постоянный сигнал тревоги и запускаю ApplyChanges, расширение контекста самопроверки пытается установить исходное значение (null) в контексте EF (в SetValue в расширениях контекста), но молча пропускает это потому, что ClrEquivalentType для EdmType не допускает значения NULL 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, потому что он создает предложение WHERE в операторе UPDATE, где он использует 0 (ноль) в качестве исходного значения внешнего ключа пользователя вместо правильного «равно нулю». (Предложение WHERE является частью механизма оптимистичного параллелизма EF, где исходные значения свойств, отмеченных «фиксированным» режимом параллелизма, проверяются по свойствам в базе данных).

Обнуляемые внешние ключи / примитивные типы не полностью поддерживаются в объектах самопроверки для EF? Если нет, должен ли я использовать фиктивные сущности вместо null или есть другие обходные пути?

Обновление Я попытался воспроизвести проблему без STE, но простой EF, похоже, хорошо справляется с оптимистичным параллелизмом для внешних ключей, допускающих значение NULL, так что это проблема STE, а не проблема EF. Существует множество проблем с объектами самопроверки, поэтому неудивительно, что здесь есть сбой. Если я найду обходной путь, который можно реализовать в сценарии STE T4, я опубликую его здесь.

7
задан Holstebroe 13 September 2010 в 08:22
поделиться

1 ответ

Да, внешние ключи, допускающие значение NULL, безусловно разрешены. Мы используем их повсеместно. Вы не показываете свою базу данных или модель, поэтому трудно определить, в чем может быть проблема, но похоже, что Entity Framework не может определить первичный ключ одной из задействованных таблиц. Возможно, у вас его нет, может потому, что один из них — вид? Я предполагаю здесь, потому что вы не даете много информации о том, что вы делаете.

0
ответ дан 7 December 2019 в 20:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: