gpt4 book ai didi

c# - 添加到 ObjectSet 的对象的多态移除不会引发 ObjectSet.IListSource.GetList() 上的 IBindingList.ListChanged

转载 作者:行者123 更新时间:2023-11-30 12:49:40 26 4
gpt4 key购买 nike

概述/描述

简单:从TEntity派生 的运行时类型对象的多态删除添加到 ObjectSet<TEntity>不会提高 IBindingList.ListChanged IBindingList 上的事件ObjectSet<TEntity>.IListSource.GetList() 返回的对象方法。

但是,删除运行时类型匹配 的实例 TEntityListChanged 上得到有效通知事件。

为了澄清,在任何时候,对象都有效地从底层集合或数据 View /存储中删除,但是当这些对象是严格从实际 TEntity 派生的类型的实例时用过,ListChanged不会引发事件以通知其删除。

对于集合的运行时多态性的适当数据绑定(bind)支持而言,这只是一个现象性的 BUG。

复制

模型设置

  1. 每个类型的策略表。
  2. 针对 Server 2012 Express 上的综合 SQL 数据库映射和验证实体模型。

这是实体层次结构(伪 UML):

FiascoEntityContext : ObjectContext
+ Foos : ObjectSet<Foo>

Foo : EntityObject
+ Id: Int32
+ Name: String

SpecialFoo : Foo
+ SpecialProperty: String

演示代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data.Objects;

namespace FiascoEF {
class Program {
static void Main(string[] args) {
using (FiascoEntityContext context = new FiascoEntityContext()) {
//
// add some foos
//
context.Foos.AddObject(new Foo { Name = "Foo1" });
context.Foos.AddObject(new BetterFoo { Name = "BetterFoo1", SpecialProperty = "Something Special" });
context.SaveChanges();
//
// show the contents
//
Console.WriteLine("Listing all foos:");
foreach (var foo in context.Foos) {
Console.WriteLine(" Got {0}: Id={1} Name={2} (State={3})", foo, foo.Id, foo.Name, foo.EntityState);
}
//
// attach handler for the ListChanged event of the IBindingList returned by context.Foos as IListSource
// NOTE: have to do this here bacause SaveChanges() above will reset the internal IBindingList
//
var bindingList = (context.Foos as IListSource).GetList() as IBindingList;
bindingList.ListChanged += new ListChangedEventHandler(bindingList_ListChanged);
//
// delete all foos and show state. expect the event handler above to be invoked.
//
Console.WriteLine("Deleting all foos:");
foreach (var foo in context.Foos) {
context.Foos.DeleteObject(foo);
Console.WriteLine(" Deleted {0}: Id={1} Name={2} (State={3})", foo, foo.Id, foo.Name, foo.EntityState);
}
context.SaveChanges();
}
}

static void bindingList_ListChanged(object sender, ListChangedEventArgs e) {
Console.WriteLine(" Event on {0}: {1}", sender, e.ListChangedType);
}
}
}

预期结果

Listing all foos:
Got FiascoEF.Foo: Id=257 Name=Foo1 (State=Unchanged)
Got FiascoEF.BetterFoo: Id=258 Name=BetterFoo1 (State=Unchanged)
Deleting all foos:
Event on System.Data.Objects.ObjectView`1[FiascoEF.Foo]: ItemDeleted
Deleted FiascoEF.Foo: Id=257 Name=Foo1 (State=Deleted)
Event on System.Data.Objects.ObjectView`1[FiascoEF.Foo]: ItemDeleted
Deleted FiascoEF.BetterFoo: Id=258 Name=BetterFoo1 (State=Deleted)

实际结果

Listing all foos:
Got FiascoEF.Foo: Id=257 Name=Foo1 (State=Unchanged)
Got FiascoEF.BetterFoo: Id=258 Name=BetterFoo1 (State=Unchanged)
Deleting all foos:
Event on System.Data.Objects.ObjectView`1[FiascoEF.Foo]: ItemDeleted
Deleted FiascoEF.Foo: Id=257 Name=Foo1 (State=Deleted)
Deleted FiascoEF.BetterFoo: Id=258 Name=BetterFoo1 (State=Deleted)

研究

通过反射器发现实际IBindingList返回的类型是 ObjectView<TElement> ,并且此类型将删除操作委托(delegate)给内部 IObjectViewData<TElement> .为该接口(interface)找到的实现是 ObjectViewQueryResultData<TElement>其中定义:

public ListChangedEventArgs OnCollectionChanged(object sender, CollectionChangeEventArgs e, ObjectViewListener listener) {

ListChangedEventArgs changeArgs = null;

if (e.Element.GetType().IsAssignableFrom(typeof(TElement)) && _bindingList.Contains((TElement) (e.Element))) {
...
changeArgs = new ListChangedEventArgs(ListChangedType.ItemDeleted, ...);
...
}

return changeArgs;
}

支票:

if (e.Element.GetType().IsAssignableFrom(typeof(TElement)) && ...) { ... }

似乎是假的...可能是以下内容?

if (typeof(TElement).IsAssignableFrom(e.Element.GetType()) && ...) { ... }

最佳答案

很公平,向 Microsoft 报告了错误 — http://connect.microsoft.com/VisualStudio/feedback/details/749368 ...他们似乎已经承认了这个问题,但不清楚他们将做什么。

请记住,我们谈论的是 IBindingList ObjectSet<T> 检索到的实现当被视为 IListSource出于数据绑定(bind)的目的,因此预计会触发事件,就像在同类列表的情况下一样。

我通过定义一个继承自 ObservableCollection<T> 的类来摆脱困境并包装 ObjectSet<T> , 然后执行 IListSourceDbExtensions.ToBindingList<T>(this ObservableCollection<T>) 的帮助下扩展方法。

或者,我可以继续并开始使用 DbContext完全是 API,但定义了我自己的 ObservableCollection<T>允许我继续使用 ObjectContext现在,这就是我想要的。

关于c# - 添加到 ObjectSet<TEntity> 的对象的多态移除不会引发 ObjectSet<TEntity>.IListSource.GetList() 上的 IBindingList.ListChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11061548/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com