Make sure Entity framework always reads from database? - entity-framework

I have this applikation that is actually two applications, a webapplication and a console application. The console application is used as a scheduled task on the windows machine and is executed 3 times a day to to some recurring work. Both application uses the same Model and repository that is placed in a seperate projekt (class library). The problem is that if the console application need to make som changes to the database it updates the model entity and save the changes to database but when this happens the context in the webbapplication is unaware of this and therefore the object context is not refreshed with the new/updated data and the user of the application can not see the changes.
My question is: Is there a way to tell the objectcontext to always load data from the database, either on the hole objectcontext or for a specific query?
/Regards Vinblad

I don't think you should have this problem in web application. ObjectContext in web application should be created per request so only requests processing during update should be affected.
Anyway there are few methods wich can force ObjectContext to reload data. Queries and load functions allow passing MergeOption which should be able to overwrite current data. But the most interesting should be Refresh method especially with this application.

By Using a DbSet you can you can also make use of the .AsNoTracking() method.

Whenever you run something like
context.Entities.FirstOrDefault()
or whatever query against the context, the data is actually fetched from the database, so you shouldn't be having a problem.
What is your ObjectContext lifetime in the webapp? The ObjectContext is a UnitOfWork, so it should be only created to fetch/write/update data and disposed quickly afterwards.
You can find a similar question here:
Refresh ObjectContext or recreate it to reflect changes made to the database?

FWIW, creating a new (anonymous) object in the query also forces a round trip to the database:
' queries from memory
context.Entities.FirstOrDefault()
' queries from db
context.Entities.Select(Function(x) New With {p.ID, p.Name}).FirstOrDefault()
Please forgive the VB, it's my native language :)

Related

EF Core and caching of results

I'm working on an Websocket application. When the client connects to the server, the websocket session get one dbcontext from dependency injection
Services.AddDbContext<Db>
This dbcontext will be the same for the whole websocket session. The problem is that the dbcontext will cache results. So if the websocket session is open for for example two hours and its reading the same data twice, while the data has been changed outside that dbcontext, the dbContext will give give invalid data back as response for the query. (the cached result from last query). There is serveral examples on how to avoid this, but it has to be done on every query. This is not really practical and somewhere in the code it might be forgotten and you have a chance to get invalid data.
Is there someway to permanently disable caching?
I think that you try use Entity Framewor in a very wrong way, DbContext is not supposed to work this way and it is not a cache per say, although it keeps some data in memory for you.
In your case I would suggest to either
Query The database every time as you suggested.
Or even better
Take advantage of proper caching mechanisms.
The decision if you should use sql server or a caching mechanism is based on how long you want to keep the data and how often you want to query them. If it is permanent and not query so often then it is sql server. If it is a couple of hours and you query very often it is better caching.
As a caching mechanism you can use:
The default MemoryCache, but it has quite limited functionality and it is restricted to the application level, so if you run multiple instyance of yor application this solution will not work out.
A distributed cache solution, like Redis, which supports a lot of functionality and you can connect many instances of your applications.

How is tracked data in an ORM kept up to date?

How does something such as Entity Framework track changes to it's data when data changes could originate from other sources? For eg: When there is a cluster of the same asp net core app running and if one app updates a record but it's being tracked on a different instance and that instance receives a get request wouldn't it send out of date data?
Basically, how do ORMs preserve ACIDity if they perform local change tracking?
It helps to think of EF contexts and their local caching especially as short-lived. When you read an entity, that entity's "lifespan" should be thought of as matching the lifespan of the DbContext that originated it. Beyond that lifespan, the object is effectively just assumed to be like any other potentially stale copy of the data. Even within that lifespan it does not synchronize with the underlying data source, so the point of truth is when SaveChanges is called. The caching EF provides is more around the scenario of: "I'm going to load some entities, and those entities reference other entities. As the code iterates over the entities, when it comes across a reference to something else, EF will check to see if that something else has already been loaded and serve it before going to the DB." So in that sense, a long-lived DbContext is a bad thing because some of that cached data could be quite old and stale, and as the DbContext loads more data sifting through these tracked entities gets slower and the context consumes more memory.
In web applications, the DbContext is scoped typically to a single request, or shorter than that. (Unit of Work) This means that edits on concurrently handled requests aren't notified of each other's changes, and neither request sees changes made by other sources between the time those request contexts loaded their data and prepared to save. EF can be made aware of what to check for concurrent changes, normally a row version timestamp, and can block an update where this check fails. Beyond that, it is the developer that has to determine what action to take. This often means catching a concurrency fault and then handing off to an appropriate handler to log the details and notify the user. This could be a First-in-wins scenario where the user is notified that their changes failed and to try again; (with the refreshed data provided) A Last-in-wins scenario where the user is prompted that there have been changes but can overwrite; (and hopefully logged the event in case there are disputes/questions) Or a Merge where the system inspects the changes and provides details of any conflicts and changes for the user to review and adjust/accept/or cancel their update.
EF can help detect this, but ultimately the developer has to code for what to do about it.
In terms of detecting concurrent edits as they happen, that requires deliberate coding to do things like communicating changes between sessions (publish/subscribe) where each session listens for updates to entities it's actively working on, and broadcasting changes to entities as it updates them. To detect possible other changes to data by other sources means another process to listen for DB updates (beyond changes it already knows about made by the system) and broadcasting those change notifications to any active sessions. Certainly a very cool thing to see working in action, but the cost & complexity that it introduces has to be justified beyond just handling concurrency issues on save. :)

how do I refresh/reload collection using same context in Entity Framework

I have a stand-alone console app which polls the db periodically for changes.
I want to ensure if anyone makes changes to the Db from the web front-end, the console app gets an updated list of entities.
I've been looking at the .Reload() method but this seems to work only on a single entity. I want my select statement on the repository layer to get a refreshed list, as well as any item changes within the list. Effectively a refresh of the whole context for this particular entity.
How do I achieve this, without creating a new context? The reason for not creating a new context is that I want to be able to still unit test and inject the repo into the consuming service without creating a concrete implementation inside the service.
Why do you need long living context? You didn't mentioned any valid reason. You can inject factory instead of context to your service. Factory will hide context creation and your service will be able to create as many contexts as it needs to. Long living context is problematic and should be avoided.
Anyway if you need to refres some data you can change MergeOption for the set (or ObjectQuery):
context.MyEntitySet.MergeOption = MergeOption.OverwriteChanges;
var data = context.MyEntitySet.ToList();

Seam - how to deatach entity

I'm working on Seam project and have following problem - there is an ajax edit form and many interactions with this form affect (mutate) underlying entity and are changed in db immediately, but I wan't those changes persisted in database only when user will press "save" button. I'm thinking about deataching entity to accomplish this but wonder how (Also looking for smarter solutions).
The changes that you are making to an entity are immediately reflected making it synchronized with database. To detach a entity, you can use entityManager.detach(object) or entityManager.clear(), but that will detach all managed entities.
EntityManager's flush-mode is FlushModeType.AUTO by default, instead try FlushModeType.COMMIT in which changes are flushed only on explicit commit/flush & then using entityManager.flush() to synchronize the persistence context to the underlying database.

Entity Framework ObjectContext: Concurrency

I am trying to use an MVC application with Entity Framework and Repository pattern
In this application, an end user may modify different entities data through multiple http requests during their session. (kind of wizard pages)
However they do commit these modifications until a final commit button is clicked
These also have the option to leave and this case, their work should be rollbacked.
I am wondering what would happen if two uses are doing the same and one of them clicks the commit button
I guess changes made by both users are committed !!!
I guess I need to create a object context by user connection or by session
Your comments are very much welcome
The context should be used only once for fetching the data initially and once for persisting.
(No long-lived 'multi-http-request' contexts).
So what you do is this:
Create context, fetch data, dispose of context.
Manage user changes to the data across multiple requests in whatever way you like (without using the context), e.g. Session, hidden fields, etc.
Create context, persist modified entities, dispose of context.
Regarding step 2 - I recommend using specific objects (ViewModels) rather than EntityObjects in the Views for user interaction.