Свойство навигации POCO не обновляется, когда внешнему ключу присваивается значение - PullRequest
0 голосов
/ 18 января 2020

У меня есть класс POCO (OPERATION), который используется в качестве сущности Entity Framework. Этот класс имеет свойство навигации (OP) и внешний ключ в той же связанной сущности (OP_ID).

В методе я получаю OPERATION, а для этого OPERATION the OP_ID и OP оба null. Когда я устанавливаю OP_ID в допустимое значение для этого внешнего ключа, свойство навигации OP остается null. Когда я явно обнаруживаю изменения в контексте, свойство навигации OP теперь назначается с правильным значением.

Пример кода

public bool UpdateOperation(operationID)
{
    IQueryable<OPERATION> operations = from o in base.ctx.OPERATION
                                                        select o;

    OPERATION operation = operations
        .Where(o => o.OPERATION_ID == operationID)
        .Include("OP")
        .FirstOrDefault();

    if (operation != null)
    {
        operation.OP_ID = opId;
    }

    // operation.OP is null here

    operation.GetContext().ChangeTracker.DetectChanges();

    // operation.OP is populated here
}

Я подтвердил, что operation на самом деле является динамическим c прокси. Для чего стоит, когда я обнаруживаю изменения, operation.OP также становится динамическим c прокси. Однако даже в этом случае присвоение другого значения для operation.OP_ID все еще требует явного вызова DetectChanges() для обновления значения operation.OP.

Обновление

В ответ на комментарий @ErikPhilips документация здесь , похоже, подразумевает, что это должно произойти. В частности:

В следующих примерах показано, как использовать свойства внешнего ключа и свойства навигации для связывания связанных объектов. С ассоциациями внешних ключей вы можете использовать любой метод для изменения, создания или изменения отношений. С независимыми ассоциациями нельзя использовать свойство внешнего ключа.

Присвоив новое значение свойству внешнего ключа, как в следующем примере.

course.DepartmentID = newCourse.DepartmentID;

...

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

Если вы используете объекты POCO без прокси, вы должны убедиться, что метод DetectChanges вызывается для синхронизации связанные объекты в контексте.

Также может быть полезен некоторый дополнительный контекст. Это устаревшее приложение, которое раньше работало непосредственно с ObjectContext вместо DbContext, хотя даже тогда с использованием EF 6. Сейчас мы переходим на DbContext API. Этот конкретный код, без каких-либо изменений, используется для демонстрации ожидаемого поведения. В частности, когда назначено OP_ID, я вижу в отладчике, что свойство OP автоматически заполняется, чтобы указывать на правильный OPERATION.

1 Ответ

0 голосов
/ 21 января 2020

В конце концов, я делал именно то, что описано в документации. Я

присваивал новое значение свойству внешнего ключа.

Да, Entity Framework справляется с этим в процессе исправления. И да, документация действительно утверждает это.

Оказывается, однако, что яйцо в конечном счете на моем лице. Я проверил классы, сгенерированные из моего шаблона T4, и увидел, что все навигационные свойства помечены virtual. Однако я проверил недостаточно подробно, чтобы отметить, что свойства внешнего ключа не были помечены 1016 *. Похоже, что это стандартное поведение шаблона T4, предоставляемого EF, используемого при работе сначала с моделью или базой данных. Я решил эту проблему, изменив эту строку в методе CodeStringGenerator.Property() в шаблоне T4

Accessibility.ForProperty(edmProperty)

на

AccessibilityAndVirtual(Accessibility.ForProperty(edmProperty))

В конце, как обычно, следуя документации (здесь требования к отслеживанию изменений EF в POCO часто приводят к тому, что зависимый код ведет себя так, как он задокументирован. Позор мне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...