2

I'm new to Entity Framework (working mostly with NHibernate with ActiveRecord before) and I'm stuck with something, that I think should be easy...

I have a User Entity, and created partial User class so I can add some methods (like with NHibernate). I added GetByID to make getting user easier:

public static User GetByID(int userID)
{
    using (var context = new MyEntities())
    {
        return context.Users.Where(qq => qq.UserID == userID).Single();
    }
}

Now in the same class I want to log moment of logging in, and I try to do:

public static void LogLoginInfo(int userID)
{
    using (var context = new MyEntities())
    {
        var user = User.GetByID(userID);
        var log = new LoginLog { Date = DateTime.Now };
        user.LoginLogs.Add(log);
        context.SaveChanges();
    }
}

The problem is I can't access user.LoginLogs because user's context is already disposed... Most likely I'm missing something obvious here, but creating always full queries like:

context.Users.Where(qq => qq.UserID == userID).Single().LoginLogs.Add(log);

doesn't seem like a good option...

I've read about Repository pattern but I think it's too big gun for such task. Please explain me what am I doing wrong. Thanks in advance!

EDIT

To picture what I'd like to do:

//somewhere in business logic
var user = User.GetByID(userID);
var posts = user.GetAllPostsForThisMonth();
foreach(var post in posts)
{
    Console.WriteLine(post.Answers.Count);
}

Normally I'm not allowed to do this because I can't get post.Answers without context...

1
  • note that GetByID will throw an exception if a record is not found. Rather use FirstOrDefault(); Commented Jul 5, 2011 at 19:00

2 Answers 2

1

You are closing the object context and then trying to add a log to the user that is detached. You need to attach the user so the objectContext know what has been changed or added.

public static void LogLoginInfo(int userID)
{
    using (var context = new MyEntities())
    {
        var user = context.User.Where(p=>p.UserID == userID); //<= The Context now knows about the User, and can track changes.
        var log = new LoginLog { Date = DateTime.Now };
        user.LoginLogs.Add(log);
        context.SaveChanges();
    }
}

Update
You can also attach the object.

public static void LogLoginInfo(int userID)
{
    using (var context = new MyEntities())
    {
        var user = User.GetByID(userID);
        var log = new LoginLog { Date = DateTime.Now };
        user.LoginLogs.Add(log);
        context.User.Attach(user);
        context.SaveChanges();
    }
}

Update

var getFirstLogin = from p in User.GetUserById(userId)
                    select p.LoginLogs.FirstOrDefault();

NB if LoginLogs is a different table you will need to use Include.

public static User GetByID(int userID)
{
    using (var context = new MyEntities())
    {
       return context.Users.Include("LoginLogs").Where(qq => qq.UserID == userID).FirstOrDefault();
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

So there is no other way? It's something that I want to avoid, because this is only the most simple example of which queries I will use multiple times and wan't to close them in methods. It's perfectly possible in NHibernate so I hoped it will work similar here...
Thanks, attaching did the job in this situation :). But please answer my last question, is this ever possible to do something like this outside context somehow: var firstLog= User.GetByID(userID).LoginLogs.First();?
you go do try something like this. var firstLog = from p in User.GetByID(userID) select p.LoginLogs.FirstOrDefault();
It doesn't work :(. I gave you this +1 for Attaching but I'll wait some more time for other answers before accepting :). Maybe that's just impossible...
0

If you are open to using stored procedures (and they work nicely with EF), you can return the user object and simultaneously add to the log table with a single call to the database.

I used to do everything with SP's in my pre-EF/ORM days, when I went to EF I tried very hard to avoid using stored procedures to avoid falling back into my old habits, but now I have found that the selective use of stored procedures you can have the benefits of both -the EF way of doing things, and the super functionality/performance that a well written SP can provide.

1 Comment

The problem is that logging is only example. I try to find a way to access full properties of my entities without creating context everywhere (which as turns out still doesn't work well when I use any shortcut methods for selecting entities). Maybe I'm too unclear in my question :). In short I'd like to manage entities in the way like it is solved in NHibernate.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.