-
Notifications
You must be signed in to change notification settings - Fork 934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for caching fetched relations with linq query provider #1952
Conversation
I should have not validated it yet maybe: I have not checked (and not seen tests about) what would happen in case of Cartesian products due to the fetches. Won't it cache, in case of bags, duplicated collection items? And causes wrong data to be cached? |
I tested it by modifying the mappings to use bags instead and when I tried to fetch multiple bags I got an |
I'm also interested in this case. Could you please clarify how collections owners are cached in this case. Are they cached per row - the same owner is serialized for each row and then put to cache? Or there is some smart logic that serializes owner only once or even unique owner is put to cache only once? |
For the bag mixed with sets case, I tend to think that before this PR, the bag would be loaded with duplicated elements due to the Cartesian products, but not cached. So loading afterward its owner in another session and lazy loading the bag should then yield correct results (from db) then cache correct results. With this PR, we would now have wrong results cached for the bag, and later loading of the owner followed by a lazy load of the bag would retrieve these wrong results from cache. Or am I wrong? |
In order to explain how this PR works I will use a simple one to many fetch first, for example:
When the query is executed for the first time it will cache the following data:
Now one would ask the following questions:
When I was doing this PR I didn't find an easy way to detect where the owner will be among the cached values especially when caching multiple collections.
The idea was to be able to batch fetch all collection items at once when batch fetching is enabled so if we fetched 3 collection we would be able to get all collection items in one cache call, which is done in #1955. When the query is executed for the second time the query result will be retrieved from the cache and the cached entites will be assembled by the Now if we have a cacheable query with a cartesian product the only difference is that we will have a lot more duplicated values. For the test I've made, the following data is cached:
I've made a test on the current master that shows that the bag can be cached with the duplicated elements, so the issue already exists. |
e6f6d15
to
5244101
Compare
Rebased for resolving conflicts. |
This PR fixes #1195 as it adds the ability to cache all fetched relations (many-to-one/one-to-many). The solution uses a special query cache result builder that appends extra values when creating the cache list that is then passed to the
IBatchableQueryCache.(Put\PutMany)
method. When fetching a many-to-one relation an additional value is added to the row of the cache list which is the id of the fetched relation. When fetching a one-to-many relation two values are added, the first is the id of the fetched element and the second is the collection id, which is the id of the entity that contains that collection. When the cached list is retrieved form the cache, the query cache will assembly and initialize all objects from the cached query and afterwards a special method is called that will remove the extra values that were added by the result builder.