Использование Reflection для удаления объекта из RIA Services EntityCollection? - PullRequest
1 голос
/ 05 января 2010

Чтобы упростить повторное использование элементов управления, мы создали решение с тремя отдельными проектами: библиотека элементов управления, клиент Silverlight и серверная часть ASP.NET. В управляющей библиотеке нет ссылок на сгенерированные RIA Services классы моделей данных, поэтому, когда ей необходимо с ней взаимодействовать, мы используем отражение.

До сих пор это работало нормально, но я столкнулся с проблемой. У меня есть элемент управления DataGrid, где пользователь может выбрать строку, нажать кнопку «Удалить», и он должен удалить объект из коллекции. В классе DataGrid у меня есть следующий метод:

private void RemoveEntity(Entity entity)
{
    // Use reflection to remove the item from the collection
    Type sourceType = typeof(System.Windows.Ria.EntityCollection<>);
    Type genericType = sourceType.MakeGenericType(entity.GetType());
    System.Reflection.MethodInfo removeMethod = genericType.GetMethod("Remove");
    removeMethod.Invoke(this._dataGrid.ItemsSource, new object[] { entity });

    // Equivalent to: ('Foo' derives from Entity)
    //   EntityCollection<Foo> ec;
    //   ec.Remove(entity);
}

Это работает на стороне клиента, но в доменной службе при методе Submit () возникает следующая ошибка:

"Оператор UPDATE конфликтует с ограничение FOREIGN KEY "********". Конфликт произошел в база данных "********", таблица "********", колонка "********". Заявление имеет было прекращено. "

Одна вещь, которую я заметил, это то, что метод службы UpdateFoo () вызывается вместо метода DeleteFoo () в доменной службе. Дальнейшая проверка показывает, что объект входит в набор изменений ModifiedEntities вместо набора изменений RemovedEntities. Я не знаю, в этом ли проблема, но это не так.

Любая помощь будет оценена, спасибо,


UPDATE

Я определил, что проблема определенно связана с вызовом отражения метода EntityCollection.Remove (). По какой-то причине его вызов приводит к изменению свойства EntityState объекта на EntityState.Modified вместо EntityState.Deleted, как и должно быть.

Даже если я пытаюсь удалить из коллекции, полностью обойдя DataGrid, я получаю точно такую ​​же проблему:

Entity selectedEntity = this.DataContext.GetType().GetProperty("SelectedEntity").GetValue(this.DataContext, null) as Entity;
object foo = selectedEntity.GetType().GetProperty("Foo").GetValue(selectedEntity, null);
foo.GetType().InvokeMember("Remove", BindingFlags.InvokeMethod, null, foo, new object[] { entity });

В качестве теста я попытался изменить метод доменной службы UpdateFoo () для реализации удаления, и он успешно работал для удаления объекта. Это указывает на то, что вызов службы RIA работает правильно, он просто вызывает неправильный метод (обновление вместо удаления.)

public void UpdateFoo(Foo currentFoo)
{
    // Original update implementation
    //if ((currentFoo.EntityState == EntityState.Detached))
    //    this.ObjectContext.AttachAsModified(currentFoo, this.ChangeSet.GetOriginal(currentFoo));

    // Delete implementation substituted in
    Foo foo = this.ChangeSet.GetOriginal(currentFoo);
    if ((foo.EntityState == EntityState.Detached))
        this.ObjectContext.Attach(foo);
    this.ObjectContext.DeleteObject(foo);
}

Ответы [ 3 ]

3 голосов
/ 29 апреля 2011

Я исследовал похожую проблему.

Я полагаю, что проблема заключается в том, что вы вызываете remove со ссылкой на EntityCollections в DomainContext в качестве корневой ссылки, а не используете сам DomainContext в качестве корневого.

Итак ...

ParentEntityCollection.EntityCollectionForTEntity.Remove (TEntity);

Создает EntityState.Modified вместо EntityState.Deleted

Попробуйте вместо ...

* +1017 * DomainContext.EntityCollectionForTEntity.Remove (TEntity);

Я думаю, что это даст результат, который вы ищете.

Надеюсь, это поможет.

2 голосов
/ 11 января 2010

Что такое «столбец» в ошибке «Ограничение FOREIGN KEY»? Является ли это поле в строке и коллекции сетки, которое соответствует этому столбцу? Возможно ли, что объект, который вы пытаетесь удалить, является столбцом в строке, а не самой строкой, которая вызывает обновление строки (обнуляет столбец), а не удаляет строку?

0 голосов
/ 11 января 2010

Я прочитал ваше обновление и похоже, что вы определили, что проблема в отражении.

Вы пытались убрать отражение с картинки?

Как в:

private void RemoveEntity(Entity entity) 
{ 
    // Use reflection to remove the item from the collection 
    Type sourceType = typeof(System.Windows.Ria.EntityCollection<>); 
    Type genericType = sourceType.MakeGenericType(entity.GetType()); 

    // Make sure we have the right type
    // and let the framework take care of the proper invoke routine
    if (genericType.IsAssignableFrom(this._dataGrid.ItemsSource.GetType()))
        ((Object) this._dataGrid.ItemsSource).Remove(entity);
} 

Да, я знаю, что это некрасиво, но иногда ...

Отредактировано для добавления

Я обновил код для удаления ключевого слова is.

Теперь об использовании объекта для вызова метода Remove. Я полагаю, что он может работать из-за позднего связывания с ним.

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