使用Reflection从RIA Services EntityCollection中删除实体?

时间:2010-01-05 16:32:52

标签: entity-framework reflection silverlight-3.0 wcf-ria-services

为了促进控制重用,我们创建了一个包含三个独立项目的解决方案:控件库,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 ChangeSet而不是RemovedEntities ChangeSet。我不知道这是不是问题,但似乎不对。

任何帮助将不胜感激,谢谢,


更新

我已经确定问题肯定来自对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 个答案:

答案 0 :(得分:3)

我一直在研究类似的问题。

我认为问题是你在DomainContext中使用EntityCollections的引用调用remove作为根引用,而不是使用DomainContext本身作为根。

因此...

ParentEntityCollection.EntityCollectionForTEntity.Remove(TEntity)已;

生成EntityState.Modified而不是EntityState.Deleted

尝试改为......

DomainContext.EntityCollectionForTEntity.Remove(TEntity)已;

我认为这会产生你想要的结果。

希望这有帮助。

答案 1 :(得分:2)

“FOREIGN KEY约束”错误中的“列”是什么?这是网格行和集合中与该列共存的字段吗?您尝试删除的实体是否可能是行中的列而不是行本身导致更新行(使列为空)而不是删除行?

答案 2 :(得分:0)

我阅读了您的更新,看起来您已确定问题是反映。

你是否试图从图片中取出反射?

如:

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方法,我相信它可能会因为它的后期绑定而起作用。