Разрешены ли внешние ключи, допускающие обнуляемость, в Entity Framework 4? - PullRequest
7 голосов
/ 30 августа 2010

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

В частности, у меня есть объект Alarm с отношением «много к 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 является ненулевым 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?Если нет, я вынужден использовать фиктивные сущности вместо нуля или есть другие обходные пути?

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

Ответы [ 2 ]

1 голос
/ 02 ноября 2010

Билл Хут опубликовал рабочий патч на MSDN .

0 голосов
/ 30 августа 2010

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

...