none
Design question: Where would you instanciate your EntityModelContainer? RRS feed

  • Question

  • Hi,

    I'm new to the Entity Framework, I am using 4.1 using the DbContext code generator. It really works like a charm, but I am wondering where/how I should instanciate the container and wether or not it's a good idea to keep it alive for very long.

    The application is a desktop client WPF application that uses some of the MVVM concepts.

    At the moment I am struggling in choosing one of three approaches:

     

    myApp.Infrastructure - Container declared as a public static object.

    This approach sounds easy, instanciate the container at application's startup and access it as a static class. However I'm concerned about someone keeping the application up for too long and because of this, everytime I must use the container, I must ensure the container contains the latest data from the database before showing the data to the user. Some users may never close the application.

     

    myApp.ViewModels - Container declared as a private object as part of the ViewModel's ctor.

    This approach would ensure that each time a ViewModel is instanciated, the container pulls fresh values from the database. However because a user might keep a single window open for weeks, the concerns I have about the static method would still apply.

     

    As needed - Instanciate container only when a DB call is needed through a using block.

    This approach actually looks weird to me! Basically, any access to the container would be enclosed within a using block. It sounds like this option would require more work for concurrency logic and wouldn't take advantage of some of the features of the container: CurrentValues, OriginalValues and GetDatabaseValues(). But at the same time, I ensure I am always working with recent data.

     

    Some guidance would be appreciated. I do feel like instantiating at the ViewModel level is the way to go, and add some comparison between OriginalValues and GetDatabaseValues() before reading or writing anything.

    This excerpt from the DbSet.Find method is the cause of my questionning:

    [...] If the entity is not in the context then a query will be executed and evaluated against the data in the data source [...]

    The way I understand it, if the entity IS in the context, it won't check the DB. But if the context has been alive for days, it might contain obsolete data... am I reading that wrong?

    Thank you so much!

    Wednesday, October 26, 2011 7:38 PM

All replies

  • The question might not be clear enough actually (60 views and no reply! *cries*). I can handle concurency logic when writing back to the database, that's well documented on forums too.

    Is there a way to tell the container to read back from the DB every time an entity or entity set is pulled from it (i.e. not from its local cache)? Or does it do it under the hood, making this a non-issue?

    As I said above, the .Find method's explanation is what leads me to think that I should get dispose of the context as often as possible, so that it is instanciated again with fresh values form the DB (so, always use the dbContext within a using{} block would be the way to go):

    [...] If the entity is not in the context then a query will be executed and evaluated against the data in the data source [...]

    Friday, October 28, 2011 8:57 PM
  • Hi,

    For the dbcontext lifttime, you can refer this FAQ: http://social.technet.microsoft.com/wiki/contents/articles/3739.aspx

    To tell you truth, I'm not familiar with WPF, so I couldn't give helpful suggestions, thanks for understanding, but I'm not sure about the "Find" method.

    ----------------------------

    The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.

    Find is different from using a query in two significant ways:

    • A round-trip to the database will only be made if the entity with the given key is not found in the context.
    • Find will return entities that are in the Added state. That is, Find will return entities that have been added to the context but have not yet been saved to the database.

    ----------------------------

    You can refer here: http://blogs.msdn.com/b/adonet/archive/2011/01/28/using-dbcontext-in-ef-feature-ctp5-part-3-finding-entities.aspx

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, October 31, 2011 9:20 AM
    Moderator
  • Hi Alan, thank you for taking the time.

    Unfortunately, I did hit both links on past researches and they do not answer my question. Even though the TechWiki states that a global static instance is fine in my type of application, it doesn't explain anything about my concern.

    My issue isn't related to WPF, so it's fine if you're not familiar with it :)

    If I undertstand correctly, there are only 2 ways to ensure that you're working with fresh data:

    1. Work from a new instance of the container.
    2. Mark entries as Modified, use .SaveChanges(), catch exceptions, reload every single entry that didn't match (http://blogs.msdn.com/b/adonet/archive/2011/02/03/using-dbcontext-in-ef-feature-ctp5-part-9-optimistic-concurrency-patterns.aspx)

    Because of the above, I will therefore use the "using" block approach to ensure I'm always working from the freshest data from the DB on items that are likely to change as the user navigates the application.

    If someone has any clue in how to force the Container to work with DB values unless we explicitely use the "Local" container, it would be greatly appreciated. Thank you!

    Monday, October 31, 2011 6:20 PM