Entity Framework - проблема работы с отсоединенными объектами

Итак, в этом примере у меня есть родительский объект под названием Template. У шаблона всегда есть тип. Тип - это FK, который, скорее всего, уже существует. Проблема возникает при создании нового шаблона и добавлении к нему типа. После добавления типа и перехода к добавлению шаблона вы получаете сообщение об ошибке. Какая ошибка вы получите, зависит от подхода. Кто-нибудь знает, как работать с такой ситуацией?

public static void AddTemplate(Template template)
    {
        using (TheEntities context = new TheEntities())
        {
            //if (template.TemplateType.EntityKey != null)
            //{
            //    context.Attach(template.TemplateType);
            //}

            context.AddToTemplates(template);
            context.SaveChanges();

            context.RemoveTracking(template);
        }
    }

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

Вот модульный тест.

[TestMethod]
    public void CanAddAndDeleteATemplate()
    {
        Template template = new Template();
        template.Name = "Test";
        template.Description = "Test";

        TemplateType type = TemplateManager.FindTemplateTypeByName("Round");

        if (type == null)
        {
            type = new TemplateType();
            type.Name = "Round";
        }

        template.TemplateType = type;

        TemplateManager.AddTemplate(template);

        template = TemplateManager.FindTemplateByID(template.TemplateID);

        Assert.IsNotNull(template);

        TemplateManager.DeleteTemplate(template);

        template = TemplateManager.FindTemplateByID(template.TemplateID);

        Assert.IsNull(template);
    }

Модульный тест работает отлично при условии, что тип шаблона "Round" еще не существует. Я начинаю задаваться вопросом, возможны ли подобные вещи в обособленной среде.

ОБНОВИТЬ

Хорошо, я изменил свой код для AddTemplate на этот, и теперь он работает ..

public static void AddTemplate(Template template)
    {
        using (TheEntities context = new TheEntities())
        {
            if (template.TemplateType.EntityKey != null)
            {
                TemplateType type = template.TemplateType;
                template.TemplateType = null;
                context.AttachTo("TemplateTypes", type);
                template.TemplateType = type;
            }


            context.AddToTemplates(template);
            context.SaveChanges();

            context.RemoveTracking(template);
        }
    }

Таким образом, для всех существующих дочерних сущностей, которые добавляются к новому родительскому объекту клиентом, необходимо будет выполнить такую ​​работу, когда они будут готовы к сохранению. Есть ли более чистый способ сделать это? Может быть, что-нибудь более общее?

Код, который вы используете для создания объекта Template, поможет вам, а также ошибки, которые вы получаете. Я не думаю, что что-то не так с тем, что у вас есть, поэтому ошибка должна быть вне кода, который вы опубликовали.

Odd 21.01.2009 00:50

Код для создания шаблона находится в коде модульного теста внизу. Информация о классе не изменилась по сравнению с генерацией EF.

Michael M. 21.01.2009 03:30

Вы заметите, что здесь есть закомментированный фрагмент кода. При запуске с закомментированным кодом в сообщении об ошибке будет указано: Объект не может быть добавлен в ObjectStateManager, поскольку у него уже есть EntityKey. Используйте ObjectContext.Attach, чтобы прикрепить объект с существующим ключом.

Michael M. 21.01.2009 03:30

Если вы раскомментируете код и присоедините объект, который он хочет присоединить, вы получите следующее: объект с таким же ключом уже существует в ObjectStateManager. Существующий объект находится в состоянии "Не изменено". Объект можно снова добавить в ObjectStateManager, только если он находится в добавленном состоянии.

Michael M. 21.01.2009 03:31

Извини, что не ответил тебе раньше. Теперь проблема имеет гораздо больший смысл. Можете ли вы опубликовать код, который вы используете, в FindTemplateByID?

Odd 21.01.2009 09:05

Код никогда не заходит так далеко. Как только он пытается вызвать context.AddToTemplates (template); в методе AddTemplate будет ошибка.

Michael M. 21.01.2009 17:58

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

Michael M. 21.01.2009 19:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
7
9 060
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Изменение кода на это позволяет диспетчеру состояния объекта отслеживать изменение и разрешать добавление шаблона.

public static void AddTemplate(Template template)
    {
        using (TheEntities context = new TheEntities())
        {
            if (template.TemplateType.EntityKey != null)
            {
                TemplateType type = template.TemplateType;
                template.TemplateType = null;
                context.AttachTo("TemplateTypes", type);
                template.TemplateType = type;
            }


            context.AddToTemplates(template);
            context.SaveChanges();

            context.RemoveTracking(template);
        }
    }

Другие вопросы по теме