Присоединение отключенного объекта к структуре объекта - PullRequest
2 голосов
/ 23 февраля 2012

Это беспокоило меня уже некоторое время. Моя проблема заключается в следующем. У меня есть экземпляр типа X , который называется x . X - это класс сущностей, созданный Entity Framework.

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

objectContext.Xs.Attach(x);
objectContext.ObjectStateManager.ChangeObjectState(x, EntityState.Modified);
objectContext.SaveChanges();

Пока все хорошо. Однако мой objectContext не был создан этим методом, и вдруг этот код перестал работать и выбросил InvalidOperationException со следующим текстом:

Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.

Это произошло потому, что за некоторое время до запуска этого кода был выполнен следующий код:

objectContext.Xs.ToList();

Это считывает все текущие X объекты из базы данных и тем самым добавляет их в ObjectStateManager.

Затем я изменил код следующим образом:

objectContext.Xs.ApplyCurrentValues(x);
objectContext.SaveChanges();

Это сработало нормально, но если я снова удалю строку objectContext.Xs.ToList();, я получу еще один InvalidOperationException со следующим текстом:

Объект с ключом, который совпадает с ключом предоставленного объекта, не может быть найден в ObjectStateManager. Убедитесь, что значения ключа предоставленного объекта соответствуют значениям ключа объекта, к которому необходимо применить изменения.

Так что теперь у меня возникла противоположная проблема. Этот метод не работает, потому что он не отслеживается ObjectStateManager.

Кроме того, я не нашел надежного метода определения, отслеживается ли мой x или нет, поэтому в настоящее время я добавил код, подобный следующему:

try
{
    objectContext.Xs.Attach(x);
    objectContext.ObjectStateManager.ChangeObjectState(x, EntityState.Modified);
    objectContext.SaveChanges();
}
catch(InvalidOperationException)
{
    objectContext.Xs.ApplyCurrentValues(x);
}
objectContext.SaveChanges();

Это означает, что я использую обработку исключений как обычный программный поток (вряд ли исключение, что элемент уже отслеживается ObjectStateManager), и у меня также есть проблема, что я мог бы поймать другой не связанный InvalidOperationException, который я должен был обработать по-другому.

Итак, мой вопрос. Кто-нибудь знает хорошее решение для этого или, по крайней мере, правильный способ проверить, отслеживается ли ObjectStateManager x , чтобы я мог выбрать один из методов, основанный на этом, вместо try / catch?

1 Ответ

4 голосов
/ 23 февраля 2012

Вам необходимо проверить, подключен ли объект с тем же EntityKey.Попробуйте что-то вроде этого:

string containerName = context.DefaultContainerName;
string setName = context.CreateObjectSet<X>().EntitySet.Name;
EntityKey key = new EntityKey(String.Format("{0}.{1}", containerName, setName), 
                              "KeyProperty", x.KeyProperty);
if (context.ObjectStataManager.GetObjectStateEntry(key) != null)
{
    // Apply current values
}
else
{
    // Attach and set state
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...