Skip to content
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

Cache the full list some properties are populated from in the complex properties of an object #33459

Closed
DavidThielen opened this issue Apr 2, 2024 · 6 comments

Comments

@DavidThielen
Copy link

I have several models that have a List<Tag> property of the tags associated with that model. There are 3 other lists like this. The full list of all tags (and the other 3 models) rarely changes. Maybe twice/month.

So it would be great if there was a way to:

  1. Create a DbContext
  2. Read in the full lists of these 4 models using the DbContext
  3. Any subsequent queries by this DbContext, using split queries, will pull from these existing lists rather than reading again, from the DB, the subset of the lists for the object(s) just queried.
  4. Keep this DbContext for future use, in a singleton service.

This obviously would only work for a non-tracking DbContext. But when displaying a lot of data, that generally is from a non-tracking query. And while it would still have 2 query the join tables, it would not have to query the Tag, etc. tables.

This works (I tested it). But I view it as a bad idea if this kind of use is not supported/suggested. Instead every single discussion of the DbContext says don't keep them around. Create them, use them, dispose them. Which 99% of the time is very good advice.

But I think officially supporting this use case would enable safely adding a nice optimization.

@roji
Copy link
Member

roji commented Apr 2, 2024

@DavidThielen I'm not sure I understand: would your singleton DbContext be used concurrently as multiple e.g. web requests come in? If so, that doesn't work since DbContext isn't thread-safe; you cannot use the same DbContext instance concurrently from more than one thread.

I'm also not quite understanding - if you use non-tracking queries, then the tags wouldn't be tracked (e.g. cached), and each query would retrieve them again from the database, which seems to defeat the whole purpose of the scheme.

If what you want is to cache, I'd generally advise doing that outside of EF, i.e. just do a query at startup (or whenever) and read your tags into some singleton service (which no longer has anything to do with EF), and then consult them there. Otherwise, you'll have to provide a bit more context on what you're doing there.

@DavidThielen
Copy link
Author

@roji I didn't know DbContext is not thread safe. So what I listed above won't work.

Here's what I'm trying to accomplish. I do a lot of queries, using a non-tracking DbContext, to read in objects that have 2 - 7 List properties. And yes I need those lists.

I do split queries so I see it read the base object(s), then the join table(s), then the lists of these child objects.

The thing is, for a number of these child lists, the entire list of the child objects is 20 - 70. And they're pretty small. In addition, they are almost never changed.

So logically, there can be a cache of the entire list of all these and then the query is read the base object, read the join table, then copy the members of the list from the cache. Drops the queries for each of these list properties in half.

thanks - dave

@roji
Copy link
Member

roji commented Apr 2, 2024

Right, so as I proposed above, why not just load those lists into memory, i.e. have them as actual List<string> on some singleton object, and then use them in your program as usual, possibly doing a join (client-side) with data fetched with EF?

@DavidThielen
Copy link
Author

@roji I may not be understanding your suggestion. Take the example of User.Tags, that has 4 tags in the list (the tags this user is interested in). While all the repository of all the tags does not change,

  • The users will somewhat regularly change what subset of the list is in their property.
  • This user list property is used in numerous pages, such as to only show the user events with the same tags.

So I do need that list that is unique to each user.

??? - thanks - dave

@roji
Copy link
Member

roji commented Apr 2, 2024

If each user has a different list of tags, it sounds like you need to load them from the database no? Unless you're proposing to cache the tags for all your users in memory (e.g. by having a .NET Dictionary that maps users to their tags, which you load once)?

I'm still not quite clear what it is exactly that you're trying to solve here.

@ajcvickers
Copy link
Contributor

This seems basically a duplicate of #7586.

@cincuranet cincuranet closed this as not planned Won't fix, can't repro, duplicate, stale Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants