Background: we are using Telerik OpenAccess for Data andDEvExpress XtraGrid for showing the data.
Lets assume the following to snippets.
We remove an object from teleriks objectview with objectView.List.Remove. If we do a DevXpress gridView BeginUpdate and BeginDataUpdate before (and the corresponding End*Update after) the deletion of just one object can take a lot of time (e.g. 8s by 1 object out of 3000 (the deletion of the very first object is always fast, but as soon as a second one is deleted, low speed occurs.)).
We remove an object from teleriks objectview with If we do a DevXpress gridControl BeginUpdate before (and the EndUpdate after) the deletion of just one object is displayed instantly (again 1 object out of 3000).
The problem with the later is, that also that the line looks deleted instantly, there appears an empty line at the end of the grid (for each deleted item). Only with the gridView "*DataUpdate()" methods the empty line disappears. It looks like the complete time is spend in the EndDataUpdate() method.
Now comes the interesting part why the question is asked on Tleriks site:
objectView.ResetBinding() would also cause a long runtime. Therefore I think it is not only an XtraGrid problem, but has somethign to do with the datasource itself. From the description: "Causes a control bound to the to reread all the items in the list and refresh their displayed values. (inherited from
The interesting thing is where the time is spend:
If using Teleriks JustTrace, it is shown that the XtraGrid gets row values for the sorting of rows.
The time itself seems mainly be spend in Telerik.OpenAcces.RT.PersistentPropertyDescriptor.GetValue(). Telerik seems to trigger a long - running OpenAcessRunTime.RelationalStorageManager.fetch
Why is the ObjectView rereading the data?
Is there a way to do a performant remove on the objectviews list / between OpenAccess and the XtraGrid?
12 Answers, 1 is accepted
Is it possible to send me a windows application without the DevXPress grid where I can observe the behavior? Do you experience the same slow performance with a simple Windows Forms grid? It might be helpful if we have a Windows Forms example so that we can isolate the problem to OpenAccess.All the best,
the Telerik team
To be honest i'm having Problems creating a Winforms solution with DGV.
The problem mostly occurs when data is sorted in some way (e.g. user clicked a column Header, but i see no fast solution to put the telerik datasource to something sortable without loosing the binding, so something else would be tested)
The funny Thing is that i now have a behaviour which was happenign sporadic with DX all the time with MS DGV:
If i delete a row, an empty line occur in the DGV. The code for DGV is quite simple so far:
But haven't found out how to sort the columns.
Additional Information: If i don't use openaccess, but have a simple BindingList of objects, the behaviour seems to be fast.
I am really confused as to what you want to exactly achieve. Can you tell me the exact problem so that I can prepare a sample Windows Forms application that achieves that.
Is the deletion of an item (row) from the grid slow for you? If yes, can you provide me the code that you use to bind the data to the grid and the code you use to delete the item?
Hope to resolve this issue soon.
I'll give it a try to strip it down
At a later point in time the deletion is done (that were the two code parts from original post). The object is not deleted from the same thread (e.g. another user deleted the item and the items on a second users screen should be updated. )
The second item which was removed in that way took a long time perion to refresh the XtraGrid.
If OpenAccess was not used, but the DataSource was a normal BindingList everything was acting fast.
So what i wanted to achieve was only to remove an object from the list of objects from objectview, so that it is no longer be shown in the XtraGrid.
some additional information from DevExpress:
"I have researched your project, and found that the cause of the issue is in your data source. When the grid control's data is sorted and you delete a row, the grid should resort its data. (This is the expected behavior.) However, I have detected that when the grid tries to access a field from your DataSource, the DataSource executes the Select query to fetch this data. In your case, the DataSource fetches data more then 50,000 times. This is the cause of this slowdown. It will be quicker if data is cached by a data source. "
[info following small demoproject was build with DevExpress XtraGRid and Telerik OpenAccess]
Have you tried setting the value of the 'ObjectView.PersistenceBehavior' property to 'none' or 'markForAdd'? (The default value is 'markForAddAndDelete'.) This will cause a ObjectView.Remove to just remove the object from the view and not from the database.Kind regards,
the Telerik team
That would also be a remove.
We have 2 different Problems we wanted to solve with a "soft remove"
1. If an user deletes data by error, it should be recoverable. And this recover can be in same session or in another one. Also users have independend databases which are synchronized. So if one user deletes data, also the other ones should no longer see it (normal usecase, the recovery is the extension where all users should then see it again).
2. If a remove is triggered on another machine, it is done like in example below.
If it is done in this way, sometimes an exception occures, and the DevExpress grid only shows a red cross.
The last steps of a trace Shows that the XtraGrid tries to get data, but Telerik throws an exception instead. It no longer finds an objects where properties are asked for.
Normally with databinding and just a BindingList items can be removed / added / altered without a problem and changes are reflected on UI immediatly. with the objectscope as BindingSource changes on the datasource does not seem forward INotifyPropertyChanged to XtraGrid. So it should also be a Workaround to only delete data when the data is not bound to a Grid. (Ugly, but works quite well).
Very ugly workaround:
Funilly it is also much faster if we copy the complete objectview.list in a new list<T> and remove deleted items form new list while copying and then asserting the new list as the objectsviews source. This is very ugly to go each time one time through complete list, but nevertheless it seems to be fast (but this is a point where using the ORM lets us create ugly Workarounds, for the project an openaccess subscription was made since the days of Vanatec, and a lot of extras where coded for the old api so it will not so easy replaced with the new one or another product (even the demo project with new api showed similiar speed problems).
So i still search for a better solution to soft delete an object with telerik.
There is no way to perform a 'soft delete'. The objects in the ObjectView are directly bound to an underlying ObjectScope. Any changes to these objects are tracked by this ObjectScope. You can use the 'PersistenceBehavior' property, as mentioned before, to control how 'Add/Delete' function but this is applicable for all objects.
If you want to have 'soft delete' functionality then you will need to maintain your own list of objects that need to be updated on the database and then attach this list to the ObjectView so that these objects are tracked.
the Telerik team
I think the core problem is still that if i remove objects from objectscope, this change is not imm. pushed to the XtraGrid (funilly a test with an IBindingList does not show this problem).
So the hole thing is only a big workaround for the Telerik.OpenAccess.Exceptions.NoSuchObjectException.
As the remove was so slow, we now copied the objects just from the objectscope to a list, filter the soft removed items and then add the list as source of objectscope again.
This design looks awful, but is faster then objectscope.list.Remove (which took for a 3000 object list ~20s). With this it looks from a customer view like an instant, fluent update of the grid.
From what I understand, you are deleting an object in 1 form and expect that the grid in another form is refreshed and the deleted object is no longer visible. If each form has it's own objectscope, the objectscope has no way to know that an object is deleted from another scope. You would need to manage this on your own; by starting a new transaction on the scope so that the objects are fetched again. If the scopes are obtained from a single database instance (same application) then you can use the 2nd Level cache to cache objects. If objects are deleted in 1 scope then they are evicted from the 2nd level cache also.
I have not been able to reproduce the problem with deletion and the grid. If I delete an object it is immediately removed from the grid and the delete also is not slow.
"From what I understand, you are deleting an object in 1 form and expect that the grid in another form is refreshed and the deleted object is no longer visible. If each form has it's own objectscope, the objectscope has no way to know that an object is deleted from another scope. "
Yes. Therefore we keep lists of objevtviews which are pointing to objects of same types (and also the conenction to the appropriate grids, to make sure we reach everything if we delete an object)
We push the changes to the other scopes, but do not see that the XtrGrid also gets the changes.
- just delete it often the "redcross"-XtraGrid stall occured.
- delete it from objectscope.list it was slow (what you already could reproduce in the other post)
- update the complete list (manually go through each item, copy the non deleted to a new list) and put the updated list as source of the objectscope it i fast, but.. it seems like a very bad style to copy each object to another list, and reattach it to get an update of only one item...
The bad thing is that the DevExpress support is insisting that the Telerik.OpenAccess.Exceptions.NoSuchObjectException:
is a Telerik exception, and therefore they wouldn't have a problem (We tried with a nromal BindingList, where the problem also does not occur).
The additional benefit that the ObjectView provides over the standard bindingsource is that you add and delete operations are tracked buy the underlying scope. If you do not really want to use the delete functionality you should use the standard binding source and set the Data source property to point to a list of persistent objects that you obtain from the scope. Any changes to the objects are still tracked by the scope. Additionally you can decide which objects to delete and which not explicitly.
Regarding keeping multiple forms in sync, if 1 form deletes an object you can denote the rest of the forms (scopes) and begin a new transaction on them so that the changes are reflected. You should enable the 2nd level cache so that the objects are not fetched from the database again. Since the object is deleted by 1 scope if you try to delete it from the other you will get a 'NoSuchObjectException' and hence the red cross.