.NET 需要一个真正的数据感知和数据驱动网格,使用 GUID 作为行句柄

发布于 2024-11-29 14:31:09 字数 976 浏览 0 评论 0原文

我正在寻找适用于 .NET 的数据感知网格,该网格已针对底层数据集的重复更改进行了优化。我将举一个例子来展示我在该上下文中优化的含义,因为几乎所有网格都允许您更改数据源。但追溯到 OCX 时代,更改数据源已经给数据感知网格带来了问题。

这种数据感知的数据驱动网格不得使用整数行句柄。 它必须使用 GUID 行句柄。这是该网格最重要的一个要求。

底层数据集的每一行都分配有一个 GUID rowHandle,而不是整数,无论​​数据行如何排序或分组,数据行的 GUID rowHandle 都会保留下来,并且可以通过其 rowHandle 立即检索数据行。

当当前焦点行的 GUID 与最近获得焦点的行的 GUID 不同时,会触发网格的 FocusedRowChanged 事件。 [编辑:在使用整数行句柄的网格,通常情况下,当数据源更改时, FocusedRowChanged 事件不会触发,因为焦点行位置尚未更改;例如,焦点位于数据源更改之前的第一行,焦点位于数据源更改之后的第一行;即使底层行数据完全不同,整数行句柄也是相同的。]

我希望网格的行为真正具有数据感知和数据驱动;例如

Grid.GroupByColumnNames = {"customername","city"};
Grid.Groups["customername"].ExpandedValues = {"Acme Widgets", "Foo Industrial"};
Grid.Groups["city"].ExpandedValues = {"New York","Miami"};

,现在,如果我清除了上面网格下方的数据集,并用另一个数据集替换其数据源,该数据源也有客户名和城市列,并且该列中包含值 Acme Widgets 和 Foo Industrial,则网格将按customername 和 city 列,并展开这些公司(如果 PreserveGroupingsWhenDataSetChanges 标志设置为 True)。

I am looking for a data-aware grid for .NET that has been optimized for repeated changes of the underlying dataset. I will give an example to show what I mean by optimized in that context, since almost all grids let you change the datasource. But going way back to the OCX days, changing the datasource has caused problems for data-aware grids.

This data-aware data-driven grid must not use integer row handles. It must use GUID row handles. That is the single most important requirement of this grid.

Each row of the underlying dataset is assigned a GUID rowHandle, not an integer, and no matter how the datarows happen to be sorted or grouped, a datarow's GUID rowHandle stays with it, and a datarow can be instantly retrieved by its rowHandle.

The grid's FocusedRowChanged event is fired when the GUID of the currently focused row is not the same as the GUID of the row that most recently had the focus. [EDIT: In a grid that uses integer row handles, it's often the case that when the datasource is changed the FocusedRowChanged event will not fire because the focused-row-position has not changed; e.g. the focus was on the first row before the datasource change and the focus is on the first row after the datasource change; the integer row handle is the same even though the underlying row data is completely different.]

I want the grid to be truly data-aware and data-driven in its behavior; e.g.

Grid.GroupByColumnNames = {"customername","city"};
Grid.Groups["customername"].ExpandedValues = {"Acme Widgets", "Foo Industrial"};
Grid.Groups["city"].ExpandedValues = {"New York","Miami"};

Now, if I cleared the dataset the underlies the grid above and substituted another dataset for its datasource, which also had customername and city columns, and contained values Acme Widgets and Foo Industrial in that column, the grid would group the new dataset by the customername and city columns, and expand those companies (if a PreserveGroupingsWhenDataSetChanges flag is set to True).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

压抑⊿情绪 2024-12-06 14:31:09

这个问题有根本性的错误,这就是为什么几个月后没有人提供一个好的答案。即使数据的主键是 GUID,也不能证明控件的行句柄是 GUID。事实上这是一个非常糟糕的主意。 GUID 为 128 位(16 字节),而 int 通常为 32 位 - 但比位数(在某些环境中为 64)更重要的是 int 操作是原子的,这意味着您可以读取/写入 int,而无需在之间锁定线程并且性能更高。因此 GUID 具有更高的内存占用和更高的处理成本(读/写每个都需要多个操作)。

因此,实际上任何控件都应该在视觉上使用快速/精益代码,并在必要时引用数据源来获取主键或其他数据位。

我对网格的体验和想法

我碰巧喜欢 winforms 的 DevExpress 控件,也使用它们的数据层组件 XPO。然而,有多个组件供应商具有类似的控件和数据层(通常都共享将行句柄与数据主键分离的功能)。

在 DevExpress 中,他们有一个出色的数据感知网格,并提供大量事件供您关联各种可能的更改。

XPO 数据层可以使用任何内容作为主键,包括 int 或 Guid。我与许多其他开发人员一起使用 Guid,因为它能够从远程计算机或离线数据插入主键(我不能说我曾经负责过表中记录超过 20 亿条的数据库,但是也许你是)。

虽然我的数据的主键可能是 GUID,但行句柄仍然是整数。这在幕后会比 Guid 快得多。然而,它们仍然提供了一堆在可视索引、行句柄和数据源索引之间来回切换的方法,以及一些通过行句柄获取底层数据源行的方法。这在许多提供行句柄(而不是数据主键)的控件事件中非常有用,您只需使用一行代码即可通过行句柄获取数据源记录。

另外,一般来说,如果您使用基于字符串的索引器访问集合,如上面的伪代码所示,组件只需在幕后执行 List.IndexOf() 类型的调用,然后将其传递给索引器为 int 索引。所以你实际上仍在幕后使用基于 int 的索引。即使某些组件公司将 GUID 用于行句柄,他们也会在幕后将这些 GUID 放入哈希集或字典中,以查找实际使用的 int 索引。因此,无论如何,这一切都只是整数之上的层,因此他们只是将其抽象化,并让您在需要时在代码中实现此类内容(而不是将其构建到组件库中)。

建议

最重要的是,我认为您可以使用 DevExpress Grid 完成上面描述的所有内容,但必须放弃 GUID 行句柄并稍微改变您的策略。如果您的应用程序需要这种反向查找,您可能需要构建自己的 GUID 以将行句柄索引作为哈希集或字典。如果所有行句柄始终都是 GUID,这可以帮助您避免性能问题,但仍然可以在 GUID 和行句柄之间进行向前和向后转换。

There is something fundamentally wrong with this question which is why after several months nobody has provided a good answer. Even if your data's primary key is a GUID it does not justify having the row handles for a control being GUIDs. In fact this is a pretty bad idea. GUIDs are 128 bits (16 bytes) while ints are generally 32-bits - but more important than the number of bits (say it was 64 in certain environments) is that int operations are atomic meaning you can read/write an int without locking between threads and is higher performance. So GUIDs have higher memory footprint and higher cost for processing (reading/writing would be multiple operations each).

So really any control should be using fast/lean code visually and just referencing the datasource when necessary to fetch the primary key or other bits of data.

My Experience With and Thoughts About Grids

I happen to like DevExpress controls for winforms and also use their data layer component XPO. However there are multiple component vendors with similar controls and data layers (which generally all share the feature of separating rowhandles from data primary keys).

In DevExpress they have an excellent grid which is Data Aware and provides a multitude of events for you to tie into for all sorts of possible changes.

There XPO datalayer can use anything for a primary key including either an int or Guid. I use Guids along with a lot of other developers due to the ability to insert primary keys from remote machines or offline data (I can't say I've ever been responsible for a database with more than 2 billion records in a table, but maybe you are).

While the primary key for my data may be a GUID the row handles are still ints. This will be significantly faster behind the scenes than an Guid would be. However, they still provide a bunch of methods for going back and forth between the visual index, row handle, and data source index as well as a few methods for fetching the underlying data source row by the row handle. This is useful inside many of the control's events which provide row handles (not data primary keys) where you'll simply grab the data source record by the rowhandle with one line of code.

Also, generally speaking, if you access a collection using a string based indexer as in your pseudo code above, components simply do an List.IndexOf() kind of call behind the scenes which is then passed on to the indexer as an int index. So you are really still working with int based indexes behind the scenes. Even if some component company used GUIDs for rowhandles, they'd be putting those GUIDs into a hashset or dictionary behind the scenes to lookup the int index to actually use. So it'd all just be layers on top of ints anyway, so they just leave it abstract and let you implement this kind of stuff in your code if you need it (as opposed to building it into a component library).

Recommendation

The bottom line is that I think you can accomplish everything you described above with the DevExpress Grid but will have to let go of the GUID rowhandles and change your strategy a little. You may need to build your own GUID to rowhandle index as a hashset or dictionary if your application requires this kind of reverse lookup. This saves you from the performance issues if all row handles were always GUIDs but still gives you both forwards and backwards translation between GUIDs and rowhandles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文