Hi, The following example proves that we can not query for objects which have been newly added. The result of the query below gives a count = 0. Is it true that DO4 does not see the objects in the cache? If true, how do we get these (without persisting the data to the DB)? Regards Paul Sinnema Diartis AG
Updated at 13.07.2010 16:41:36
Hi Alex, You could have read it from the comment in the example :o (// Opens the Session with DisconnectedState attached and Connect() executed) What about the second question? How do we get them without persisting the data to the DB? If there's no way to get them this will lead to unwanted results. We don't want to persist anything until all data is correct. Take for instance a real KLIB (our application) example. Some of our lists use LINQ queries to refresh their content (the query is handed over as a parameter and kept inside the list for later use). This construction will become impossible if the data in the cache is never found. Any Add() would not be noticed by the list. IMHO the Cache should be transparent to LINQ or in other words, any entities added to the DisconnectedState should become visible in LINQ Queries that are executed against it. Regards Paul Sinnema Diartis AG Updated at 13.07.2010 19:46:19Hi Alex, Well, the code does run, but it only returns the same rows already fetched using a DB query. In the Example below q1 and q2 both return the same amount of rows (in my case each 3 rows). When I don't execute q1 then no rows are returned. What I also see is that after executing 'new CommunicationKindType();' the Versions collection in the DisconnectedState has a count of zero (0).
Regards Paul Sinnema Diartis AG Updated at 14.07.2010 8:20:33Hi Alex, I still don't get it completely. Are you telling me that locally added entities don't show up in the DisconnectedState.Versions and there is no way we can get all of them (remote and local together) without persisting the Data to the DB? You must be kidding me. So there's no way we can get all of the cached entities including the freshly added ones without persisting the data to the DB? IMHO that is a flaw in DO4's architecture. Can you explain to me what the concept is behind this, because I'm totally missing the point. The cache should be totally transparent for fetches and changes, meaning that any Entities in the cache together with the changes made to the cache (this includes all CRUD actions) are all visible at anytime (without persisting the data to the DB, i.e. totally local). The DisconnectedState is completely useless, to us, when we can not see all CRUD changes in it at any given time. It would mean that in order to see all the changes, any CRUD action should immediatly be persisted to the DB. This will absolutely lead to inconsistent data. We could maintain a manual transaction and only commit/rollback at times we wanted, but, even with optimistic locking, that would cause many locks in the DB, which in turn would lead to unwanted deadlock situations (coffee-break syndrom). [Andres Rohr]Or, another solution for us would be if we could call a special 'ApplyChanges()' call that plays back the changes, of the DisconnectedState, to the Session (or Domain cache) without going to the DB. So a LINQ query would see the changes too. Regards Paul Sinnema Diartis AG. Updated at 15.07.2010 6:10:49Alex, Somehow I've got the feeling that several topics are related. We've got:
Could it be that we get the 'Version mismatch' because of the 'Object Reference Changed' or 'Disconnected.Versions' problem? Regards Paul Updated at 15.07.2010 6:47:48Alex, On the Version issue. I had added a Guid to the AbstractEntity (our 1 and only HierarchyRoot element). After setting the MergeMode to PreferSource, I got an Exception saying that a conversion from Guid to string was not possible. Maybe a hint on where the problem lies? Regards Paul Updated at 15.07.2010 11:11:03at Xtensive.Storage.DisconnectedState.RegisterState(Key key, Tuple tuple, VersionInfo version, MergeMode mergeMode)
at Xtensive.Storage.DisconnectedState.RegisterState(Key key, Tuple tuple)
at Xtensive.Storage.Disconnected.DisconnectedSessionHandler.RegisterEntityState(Key key, Tuple tuple)
at Xtensive.Storage.Linq.Materialization.ItemMaterializationContext.Materialize(Int32 entityIndex, Int32 typeIdIndex, TypeInfo type, Pair Updated at 22.07.2010 12:20:31We still have some problems with this (I think it belongs in this thread). During the ApplyChanges() we now get the following exception:
Stacktrace:
This thread was imported from our support forum. The original discussion may contain more detailed answer. |
First of all, the solution: DisconnectedState.Versions allows you to get all pairs of Key and VersionInfo objects it caches. So nearly this method will return all the objects of type T cached in DisconnectedState:
I didn't tested it, so there might be non-essential mistakes. That's the point you must (or can) use in this case instead of Query.All<t>(). This implies such "queries" will be evaluated via LINQ to IEnumerable, but this should be acceptable for relatively small data sets you have on the client. I also should explain why we can't do this automatically for queries, when DisconnectedState is attached: it is much more that just "merging" the results of local and remote queries. Results of many remote operations simply can't be "merged" to produce the right final result - e.g. this can't be done in case there is any aggregation or .GroupBy(). As far as I can judge, the only way to produce the right result is to perform almost the whole calculation on the client (= fetch almost the whole database and "crunch" the data here), which is definitely not what you would expect. So we decided to do what we really can do well: run the query remotely and bring all the data to the client. It will be merged into DisconnectedState, and exposes with the changes it caches. But these changes won't affect on remote query result. At least, the behavior we have here is fully clear. See also: viewtopic.php?f=29&t=6011#p15187 Yes, suggested method should return only the objects already fetched into the DisconnectedState, since it relies on info about versions of Entities cached in DisconnectedState. So there is no silver bullet: you have two storages, one is actually a "diff" above another, i.e. ActualStorage = DisconnectedStorage.ApplyChangesTo(RemoteStorage). Two storages on this schema are real (DisconnectedStorage and RemoteStorage), but one is virtual represenation we provide for you. And you'd like to run a query over ActualStorage, that actually doesn't exist - so to run a query there, we must either build its full view locally (not acceptable), or transform RemoteStorage to it (by applying the changes). There is no other way to run a query over this storage. Some simplest queries (e.g. using just filtering) can be executed in "remote query + local refinement" fashion, but generally that's a case you can implement by your own. LiveQuery described in another post targets exactly this problem: run the query once (e.g. remotely), bind the result to UI and see how it is changing when you modify the entities locally. > Are you telling me that locally added entities don't show up in the DisconnectedState.Versions Hmm... They should. I misunderstood you - I though you're trying to get them via Query.All<t>(). Probably, that's a bug here (i.e. only fetched versions are exposed there) - I gave you the code, but I didn't try it myself. I'll check this today. > The cache should be totally transparent for fetches and changes, meaning that any Entities in the cache together with the changes made to the cache That's exactly the case we have. Of course, except direct LINQ queries to the storage - they work remotely, and thus return result based on remote data, although we expose all the entities returned by such queries already with your modifications. > [Andres Rohr]Or, another solution for us would be if we could call a special 'ApplyChanges()' call that plays back the changes, of the DisconnectedState, to the Session (or Domain cache) without going to the DB. So a LINQ query would see the changes too. Actually, you already can do this:
The last issue isn't fixed yet - needs further evaluation. But:
The cause is:
The solution we'll use here will be nearly the same - i.e. you should give identifying names to entities created inside topmost operations:
These names will be used to establish mappings between old and new keys of same named entities. Could you publish the stack trace? I here from my team, I'm not the only one that is unable to find newly added Entities. Hmmmmm. Just removed the Guid (didn't need it anymore). The Version Mismatch remains. Regards Paul |
Do you use attached DisconnectedState (this isn't clear from the sample)?
If yes, this is correct: we never flush the changes automatically in this case, but queries you run always hit the real DB.