Tuesday, October 07, 2008 5:59 PM
I 've been facing an issue whcih now I bring to you hoping to have your advice.
I have two grids, each one linked to its corresponding table (or entity).
When I load the form I call a code like the following:Code Snippet
varquery = from docs in database.Documents where docs.DocId > 0 where docs.DocReferenceID == null select docs;
this.gridDocuments.DataSource = docs;
There is a relationship 0..1, * between a transactionset and a document. The table, transactionsets, gets called in the same way.
When I show the form, and the documents start being written to the database, the grid refreshes automatically, showing the document rows as they are saved. On the other hand, and this is the problem, the gridTransactions does not *reflect any change*, even when I know that for each document a new transaction is stored in the table.
What I am doing wrong? Why can I not see the automatic refreshing on the transactions grid the same way it is seen for the documents one? The object context, which I called "database", is located in a static class.
Also, replaced the xtragrid with the visual studio one, and does not work either.
Wednesday, October 08, 2008 9:51 PMModerator
It is difficult to guess what is going on without seeing how your other query looks exactly, but I can imagine a few things that may be going on. I don’t believe this is related to the grid you are using, but with the kind of operations you are expecting to happen automatically.
When a data-bound control takes a query as a data source, this is, more less, how things work under the hood:
1. Databinding finds that ObjectQuery implements the IListSource interface, then it calls IListSource.GetList() on it to obtain the binding list (an object that implements IBindingList, and that databound controls know how to communicate with).
2. The query is executed, and the results copied to the binding list, which is itself passed to the databound control.
3. Whether an entity belongs to a binding list is decided at the time the binding list is created. The binding list does not remember which filter condition was used in the query.
4. Additions of new entities to the context do not result in the new entities being added automatically to any binding list. You can have multiple binding lists created with the same query but with different parameters, and our code does not have enough information to know whether to which binding list the new entity belongs.
5. Removal of entities from the context does result in the deleted entity being removed from all binding lists that contain it. The principle is that the binding list is a window into the current state of affairs.
6. A binding list actually has its own Add() method. If you get a reference to one of our binding lists you can “manually” add new entities to both the binding list and the context using only this Add method.
Now, a couple of tips that may be useful:
1. If you using databinding directly against a query, there is a risk that the query is going to be executed more than once if databinding asks for it more than once. The recommendation is to bind to the results, using something like query.Execute(someMergeOption).
2. Now, if you are interested in getting a reference to the binding list because you want to add new entities to it after the query is evaluated, instead of executing the query directly, you can do something like this:Code Snippetvar bindingList = ((IListSource)query).GetList() as IBindingList;
There is a more convenient ToBindingList() extension method included in the EFExtensions you may want to take a look at.
Hope this helps,
Tuesday, October 14, 2008 2:27 PM
Thanks Diego for your explanation, and sorry for the delay in answering to you.
I am working in the Client side part of a project. The client works with a local database, which can be either SqlCE, Express or full Sql Server. I've always thought that one must have separated the visual layer form the data layer, and one thing I have always avoided is to rely on visual objects to deal with data objects. For instance, not to try to use a data binding list to add entities to it while they could be added directly to the database, and the list be refreshed later. Perhaps I am too used to the old way of doing things. From this it is clear that I wouldn't try to add new entities to a binding list. Let’s say I add an entity to a list. Is there some guaranty that this entity will be propagated to all the corresponding lists (those looking to the same table)?
That brings me to another issue associated to this, and it is having more than one user attached to a database and making user A aware that user B has changed something, without having to rely on concurrency exceptions from the database.
So, is there a recommended way of visually showing that changes have been made to the database?
In L2E, the context only has the SavingChanges event, but what if I the change occurred only in one table?
On the other hand, since I am working now with normalized database structure, what originally was a single record from a table now is a bunch of fragments collected from different tables. What would be the recommended way of reflecting an update to one of the fragments in a grid?
I will take a look to the EFExtensions as you suggested.
Thanks a lot.