EF Core 2.2: use same DbContext instance get record from database multiple times, always the same result - entity-framework

I am facing an issue: we have an ASP.NET Core 2.2 Web API project with EF Core 2.2. We are using default IOC framework to create the DbContext with scope lifetime. And we have a socket pipeline connected to our ASP.NET Web API service.
I find that when we change the data in the web frontend, the socket pipeline will always get the old result (we are using .FirstOrDefault() to fetch the data, it should not be the problem with first-level cache).
So I infer that it might be because of that the scope lifetime for DbContext, so I changed it to transient lifetime. And it works! We get the modified record.
I have two questions:
Is that behavior of DbContext by design? Or maybe I have some tricky issue in my code.
How much performance will the transient lifetime DbContext cost? Since maybe I will make every DbContext transient

1) Is that behavior of DbContext by design?
Yes
For each item in the result set If this is a tracking query, EF checks
if the data represents an entity already in the change tracker for the
context instance If so, the existing entity is returned If not, a new
entity is created, change tracking is setup, and the new entity is
returned
How Queries Work
2) How much performance will the transient lifetime DbContext cost?
Very little. Especially in ASP.NET Core, which has DbContext Pooling
Since maybe I will make every DbContext transient
But you shouldn't do that. Using a request-scoped DbContext is very useful. For instance you can use the DbContext in various layers of your application without having to pass one around, and you can manage transactions more easily.

Related

How to properly use EFCore with SignalR Core (avoid caching entities)

I just found some really strange behaviour which turns out it is not so strange at all.
My select statement (query from database) worked only the first time. The second time, query from database was cached.
Inside Hub method I read something from database every 10 seconds and return result to all connected clients. But if some API change this data, Hub context does not read actual data.
In this thread I found this:
When you use EF it by default loads each entity only once per context. The first query creates entity instance and stores it internally. Any subsequent query which requires entity with the same key returns this stored instance. If values in the data store changed you still receive the entity with values from the initial query. This is called Identity map pattern. You can force the object context to reload the entity but it will reload a single shared instance.
So my question is how to properly use EFCore inside SignalR Core hub method?
I could use AsNoTracking, but I would like to use some global setting. Developer can easily forget to add AsNoTracking and this could mean serving outdated data to user.
I would like to write some code in my BaseHub class which will tell context do not track data. If I change entity properties, SaveChanges should update data. Can this be achieved? It is hard to think all the time to add AsNoTracking when querying from hub method.
I would like to write some code in my BaseHub class which will tell context do not track data.
The default query tracking behavior is controlled by the ChangeTracker.QueryTrackingBehavior property with default value of TrackAll (i.e. tracking).
You can change it to NoTracking and then use AsTracking() for queries that need tracking. It's a matter of which are more commonly needed.
If I change entity properties, SaveChanges should update data.
This is not possible if the entity is not tracked.
If you actually want tracking queries with "database wins" strategy, I'm afraid it's not possible currently in EF Core. I think EF6 object context services had an option for specifying the "client wins" vs "database wins" strategy, but EF Core currently does not provide such control and always implements "client wins" strategy.

Entity Framework Memory Management and Dispose?

I'm using EF (EF Core, actually, with ASP.NET Core on OSX, but I believe this is more of a general "newbie-style" EF question, so please read on...)
I built a little logging routine that uses EF to publish log entries to my database. Sort of like this, called from a repository class:
WebLog log = new WebLog(source, path, message);
Context.WebLogs.Add(log);
Context.SaveChanges();
Where WebLog is a simple model class, Context.WebLogs is a DbSet<WebLog> collection, and Context is obviously the DbContext. I believe this is quite straightforward.
But my question is this: if I continue to add new log entries to the Context.WebLogs collection and I never do anything like reboot my server, isn't the collection just going to grow without bounds? Is there some kind of "purge" or "flush" action I can take periodically to manage memory usage (without affecting the committed rows in the database, of course--I want those to persist). Or is DbSet some sort of a special collection that won't do this?
As mentioned by DevilSuichiro above, the recommended approach is to limit the lifetime of the instances of DbContext. E.g. in a Web application you typically use a DbContext instance per request, so an unbounded number of entities added doesn't become a problem.
The closest thing to a "flush" operation is SaveChanges() that method will not try to remove references to tracked entities, as DbContext is designed to be reused after SaveChanges().
In previous versions of EF we had a Detach() API that you could use to get rid of an individual tracked reference but we don't have that API in DbContext or anywhere in EF Core.
BTW, having an instance of DbContext that is shared between multiple requests is extremely problematic because DbContext is not thread safe.

A static DbContext object for read-only purposes in ASP.NET MVC WebAPI

I'm refactoring my ASP.NET MVC 4 WebAPI project for performance optimization reasons.
Within my controller code, I'm searching for entities in a context (DbContext, EF6). There are a few thousands of such entities, new ones are added on an hourly basis (i.e. "slowly"), they are rarely deleted (and I don't care if deleted entities are still found on the context's cache!) and are never modified.
After reading the answers to this question, to this one and a few more discussions, I'm still not sure it's a bad idea to use a single static DbContext for the purpose described above - a DbContext which never updates the database.
Performance-wise, I'm not worried about the instantiation cost, but rather about the uselessness of caching requested entities if the DbContext is created for each request. I'm also using a 2nd level caching, which makes the persistence of the context even more acute.
My questions are:
1. Regardless of the specific implementation, is a "static" DbContext a valid solution in my case?
2. If so, what would be the most appropriate way of implementing such a DbContext?
3. Should I periodically "flush" the context to clear the cache in order to prevent if from growing too big?
DbContext caches entity instances when you get/query the data. It ensures different queries that return the same data map to the same entity (based on type and id). Otherwise, if you modify the same entity in different object instances, the context would not know which one has the correct data. Therefore a static DbContext would blow up over time until the process crashes.
DbContexts should be short lived. Request.Properties is a good place to save it in Web API (maps to HttpContext.Items in IIS).

EF 4: Problems understanding DetectChanges when using POCO (no self tracking ObjectContext)

I wonder if anyone can help me?
I am having problems understanding why i need to issues DetectChanges on my POCO (non proxy) entities.
Of course i have this line to ensure that proxies are not returned.
context.ObjectStateManager.GetObjectStateEntry(order).State
And doing some research it appears if i need to check the "state" of an object then i need to issue detechChanges But why would i need to check the State of an object?
Basically I send along my POCO entity to a method that SAVES the data to a new ObjectContext (I create and destroy ObjectContext on each method)
Hence, i am having problems understanding why i would need to have ObjectContext track or be aware of changes?
Is it because that if its not aware if will not be saved?
Maybe i am miss informed but it appears that if i am using an existing ObjectContext (which i am not i am creating and destroying each time) that ensure ObjectContext is aware would be beneficial but otherwise not?
So in 1 method I am updating an object by creating a new datacontext, saving it to the db and destroying ObjectContext . Hence i am not using 2 methods, 1 method to send the update or new record and then another method for SAVING.
I would really appreciate any quick explaanations of why its needed?
Thanks in advance
Your question is little bit confusing. You are writting about Entity Framework but using DataContext which is related to LinqToSql.
The behavior differs in the way you are using ObjectContext. When you load POCO entity from database ObjectContext holds its instance in internal Identity Map. By default POCO doesn't use any kind of change tracking. When you save that POCO entity to the same instance of ObjectContext it internally calls DetectChanges to compare current entity state with stored state. This comparision defines which columns have to be updated. Internal call to DetectChanges is default behavior which can be turned off so you will have to call this method manually.
In your scenario you not using the same instance of ObjectContext. In that case you first have to Attach POCO entity to the ObjectContext. MSDN strictly says that when attaching entity it is marked as Unchanged. For that reason you have to say ObjectContext that entity has changed. You can do that for whole entity or you can define exactly which properties have changed but you have to do it manually = you have to store that information somewhere (Self tracking entities can help you with that but they have ohter disadvantages).

Does Entity Framework automatically cache the ModelBuilder model?

I am developing an ASP MVC application using Entity Framework. I was thinking of writing code to cache the object returned by ModelBuilder (as is recommended by several sources), but then I ran into this on Scott Gu's blog:
"The OnModelCreating method above will be called the first time our NerdDinners class is used within a running application, and it is passed a “ModelBuilder” object as an argument. The ModelBuilder object can be used to customize the database persistence mapping rules of our model objects. We’ll look at some examples of how to do this below.
"EF only calls the “OnModelCreating” method once within a running application – and then automatically caches the ModelBuilder results. This avoids the performance hit of model creation each time a NerdDinners class is instantiated, and means that you don’t have to write any custom caching logic to get great performance within your applications."
Does this mean that EF automatically caches the ModelBuilder object, and I don't have to write code to do it, or is this something that is only done if the OnModelCreating method is overridden, or ... ??
From the Entity Framework Blog regarding performance improvements in EF 4
Model Caching
There is some cost involved in
discovering the model, processing Data
Annotations and applying fluent API
configuration. To avoid incurring this
cost every time a derived DbContext is
instantiated the model is cached
during the first initialization. The
cached model is then re-used each time
the same derived context is
constructed in the same AppDomain.
Model caching can be turned off by
setting the CacheForContextType
property on ModelBuilder to ‘false’ in
the OnModelCreating method.
So the answer is yes for Entity Framework 4.0