1

I am creating a small data-driven desktop application using .NET 5 with WPF, ReactiveUI, Dynamic Data, and EF Core 5. The app uses a local SQLite database to store all persisted state, and relies heavily on dependency injection.

I would like to share state across my app by exposing observables of my EF entities in singleton services, so that when one part of the UI mutates state in the database, the other parts of the UI are notified of changes.

This pattern is really easy to implement if my DbContext is a singleton as well, since all of my entity objects will be shared across the application, change tracking will be automatic, and each singleton service can simply inject the DbContext and use it.

I have read in several places that it isn't recommended to have a a long-living DbContext, even in desktop applications. One article recommended one DbContext per window/dialog.

Without any details on why it's bad practice to have a singleton DbContext in a small desktop app with a local embedded database (other than "it wasn't designed to be used that way"), this just seems like unnecessary complexity. By constantly disposing of the DbContext and creating a new one from scratch, we are creating this disconnect between in memory state and EF's tracked entity state. The short lived DbContext works great in web apps since the request scope is there by default, but desktop apps don't work that way.

I'm perfectly fine with implementing a pattern that limits the scope of the DbContext if it's necessary, but it's unclear how to accomplish this while still keeping app state in sync across the app. I don't want to create a new DbContext for every single operation, but since my view models inject singleton services and don't interact with the DbContext directly, I can't exactly have one DbContext per window.

Could someone please explain in some detail an architecture pattern that would allow for the optimal use of the DbContext while also allowing view models to share state by subscribing to singleton services? Or at least point me to some examples/resources that give actual examples of how to implement this?

2
  • DbContext isn't designed for application state - it's an implementation of the Unit Of Work pattern for CRUD operations to/from your database (so you'd only create it at the moment when you actually need to query or commit a change to the underlying DB). The likely reason your idea may be considered bad practice is that it sounds like you're trying to use DbContext for something that it's not designed for. Think of DbContext as representing a single database transaction and you're getting warmer; or to put it another way, think of DbContext at the same abstraction layer as raw SQL. Dec 4, 2020 at 10:19
  • 1
    Again two downvotes for a perfectly on-topic, perfectly justifed question, and no comment why, not even a close-vote. Such uneducated behaviour is IMHO just cringeworthy. Ok, the question could be improved by giving links to the references mentioned in the question, but if that's why you downvoted, you really should have left a comment.
    – Doc Brown
    Dec 4, 2020 at 19:31

1 Answer 1

1

The patterns you may be looking for are probably Object Pool, or "Identity Map" by Fowler, in his classic book "Patterns of Enterprise Application Development". Using DBContext as an Identity Map is indeed not recommended.

The arguments in that former article boil - more or less - down to "though DBContext has indeed some internal Identity Map, it is too simple for most real-world applications". The article gives some examples, like missing transparency, no control over freeing certain objects (except all of them at once), and no option to manage no-entity classes.

That does not mean you could not try to use DBContext as an Identity Map either, and maybe you are lucky and it provides everything what version 1.0 of your application requires. However, with a growing application, sooner or later you will probably need more control over the lifespan of the objects in the pool than DBContext provides, and then you will be screwed.

I guess your best bet is probably to implement an Identity Map on your own. When you google for "Identity Map" together with some other keywords "C#", "implement" or "example", I am sure you will find some starting points.

2
  • When you don't dispose a DbContext after a certain write operation, you have no guarantee that the changes are written back to disk I don't follow. There is an explicit "SaveChanges" call that commits the changes to the database while the DbContext stays alive, so why would you need to dispose of the DbContext to ensure changes are saved?
    – wired_in
    Dec 4, 2020 at 17:49
  • 1
    @wired_in: ok, after I informed myself a little bit more, I guess my statement above was wrong. Let me fix this.
    – Doc Brown
    Dec 4, 2020 at 19:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.