2

I was writing a web app and learning entity framework along the way. I am curios if I have done something wrong though. I haven't been using dispose or using statements when querying.

Example of a Repository of mine:

public User GetUserById(int sessionId)
{
    var user = (from u in db.Users where u.Id == sessionId select u).SingleOrDefault();
    return user;
}

My User table I selected from would have foreign keys which would be associated with other tables. The cool thing, or so I thought, about entity is that I could return the entire User object (built by entity) which then would allow me to do something like this User.MyOtherTable.SomeColumn in my controller.

The problem is I relied on this and went about my merry way in my controller of grabbing the user information as well as utilizing information from the other table. I am now realizing that if I close that connection like the code below:

public User GetUserById(int sessionId)
{   using(db)
    {
    var user = (from u in db.Users where u.Id == sessionId select u).SingleOrDefault();
    return user;
    }
}

My controller no long has access to User.MyOtherTable.SomeColumn as this will be null. My true question is how important is it for me use dispose in my entity application?

allencoded
  • 6,204
  • 16
  • 65
  • 115

2 Answers2

2

I would strongly recommend that you use using statements, and also that you stop relying on lazy-loading.

Instead of selecting User objects with lazy-load properties, work out the full data you need and project that to a Model class, e.g.

public class UserWithOtherStuffModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string OtherStuff { get; set; }
}

Then in your method:

public UserWithOtherStuffModel GetUserById(int sessionId)
{
    using(db)
    {
        var user = (from u in db.Users 
            where u.Id == sessionId 
            select new UserWithOtherStuffModel{
                Id = u.Id,
                Name = u.Name,
                OtherStuff = u.MyOtherTable.SomeColumn
            }).SingleOrDefault();
        return user;
    }
}

Not only does this mean you limit the number of database calls, but you have a data contract that isn't tied to your database model. If you move that column, you simply update the query to point to the new spot/name, the view can remain unchanged.

Timothy Walters
  • 16,455
  • 2
  • 37
  • 49
  • 1
    I disagree with the statement of `using`. But only in context. In this case the OP is referring to `MVC`, which I assume means he is doing this in a `Controller`. `Controller : IDisposible` so therefore you should instantiate the context in the constructor, then dispose of it in the dispose override. Leaving the lifetime to be defined by the `using` in the actual calling code (MVC framework). – Aron Jan 23 '14 at 05:21
  • @Aron fair point, but it creates bad habits for those who haven't been doing this for long (and thus don't know where it is and isn't OK to leave off the `using` statement) and makes it less obvious to junior coders looking at the code. On the one hand I agree and would prefer it that way in this context, on the other hand I see the confusion it could create. – Timothy Walters Jan 23 '14 at 22:27
  • My general rule is this. Either use `using` or IF the calling code is a disposable, then you CAN link the lifetime to the calling class instead of the `using` (with the assumption that somewhere there is a using attached to that). – Aron Jan 24 '14 at 03:36
  • @Aron That does work on the assumption that you want to hold your database locks for as long as the disposable class is kept though, so be careful there. The `Controller` class is a place where that should be quite safe, but other disposable classes might live longer than you expect. I agree with you in principal. – Timothy Walters Jan 24 '14 at 04:31
1

So when you dispose your context, you aren't going to be able to reference properties that are lazy loaded. You'll need to make your context live longer either by having the context disposed when the controller is disposed (I don't remember if MVC does this per request or not) or by controlling the lifetime of the context using some attributes on the Action.

Some examples on how to resolve this can be found in this question, which is pretty much the same as what you are asking here.

Community
  • 1
  • 1
Darren Kopp
  • 71,547
  • 9
  • 71
  • 90