This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hello: I'm having issues where I'm trying to re-query the database through an entity however the results continued to be cached and the database isn't being hit a second time. I'm using a scoped uow. Here's an example of my function that loads the records. It is fired when the user expands a TreeViewItem so each time they expand the node I expect to hit the database to get the most fresh records. /// <summary> |
|
|
I've noticed that if I query the new UOW for the collection again, the Where is being executed. Makes sense as its a completely new object but I unfortunately take the hit of having to requery for the collection when I already have it. Is this the only way to go about doing this? Here what I had to replace from the original post snippet // Replaced with |
|
|
I'm a bit confused. Your first post seems to be indicating that you *do* want to re-query the database, so as to update the contents of the collection. But your second post seems to be indicating that you *don't* want to re-query the database because you "already have [the collection]." I *think* your issue may be that you want to re-query for the CollectionEntries collection, but not for the parent (_collection) object itself. Is that correct? If so, I think you can do this using a LINQ collection query: _collection.Query(c => c.CollectionEntries) Note however that although this will query the database for the current members of the collection, any entries which are already in the UOW will be the cached versions. Entries may be brought into the UOW when you attach the parent because attachment to a UOW cascades across associations. To ensure you get completely fresh data, do not attach _collection. Instead, write a query such as: _unitOfWork.CollectionEntries |
|
|
Hi Ivan,
You thought right, I ideally want to re-query for the CollectionEntries and from your example,
_unitOfWork.CollectionEntries.Where( e => e.CollectionId == _collection.Id ) ... will work great. Thanks for the prompt response. |
|
|
Hi again: Just a quick follow up question Ivan again queries as I think I'm struggling a bit. Using your example above, if I have my first query to get all fresh records as
var entries = uow.CollectionEntries.Where( e => e.CollectionId == _collection.Id );
Is there an easy way to pass the Where constraint around? I think the Where argument is a Func<CollectionEntry,bool> or something like that? Is it possible to additional parameters to the Func<CollectionEntry,bool>? i.e. Func<CollectionEntry,bool> whereClause = ( e => e.CollectionId == _collectionId ); Func<CollectionEntry,bool> secondClause = whereClause + ( e => e.Object is Person );
The result of that would be that I would have two queries one where the entries were constrained by the collection, and the second further constraining the original to where the entry is a Person. Am I out to lunch on this? haha It's been a long day.
|
|
|
You can just chain the Where clauses: var allEntries = unitOfWork.CollectionEntries Remember LINQ queries are deferred so you only incur a database query for queries that you actually execute -- in this case you would incur a database query for personalEntries but not for allEntries. (You can also do this using expression composition but it's a bit hairy -- the lambdas are actually Expression<Func<CollectionEntry, bool>> so you would probably need to write explicit Expression.Lambda<> invocations to compose them. This isn't stupendously hard, but it requires some familiarity with the Expressions API, and it will be verbose and obscure to most people reading your code (including you in six months' time!), so I'd try the chaining approach first!) |
|
|
Continuing with your example, after executing the personalEntries query it would be in the cache correct? How would I be able to execute the query and ensure all the records are 'fresh'? Wouldn't I require the fully LINQ query? i.e. // Get all the entries var allEntries = unitOfWork.CollectionEntries // Do some work with all Entries // Refresh all entries - easy just execute on a new session allEntries = unitOfWork.CollectionEntries .Where(e => e.CollectionId == _collectionId); In the case of the personal entries // Person query // Do some work with personal entries // Refresh all the personal entries - Ensure they are all 'fresh'! personalEntries = uow.CollectionEntries( ??? )
I have no clue what to put into ??? as I don't know the fully constrained Where clause. Sorry, I hope my explanation makes sense. |
|
|
After you execute personalEntries, the returned CollectionEntry entities are cached in the UOW. Re-executing personalEntries on the same UOW will bring back the existing cached entities. Therefore, in your final line, you must execute a query in a new unit of work if you want that query to bring back fresh entities. So you will need to create a new query on a new UOW. This can be conveniently wrapped up into a helper method via a partial class or extension method, e.g.: public IQueryable<CollectionEntry> CollectionEntriesFor( Then in your code: var originalPersonalEntries = origUOW.CollectionEntriesFor(_collection.Id) If you want to avoid repetition of the Where clause, you can wrap that up into a function as well: public static IQueryable<CollectionEntry> PersonalEntries( allowing you to write: var xxxPersonalEntries = xxxUOW.CollectionEntriesFor(_collection.Id) (where xxx can be orig or fresh). |
|
|
I see the light! Thanks for all the great help Ivan. |
|