如何使用Entity Framework访问上下文之外的实体属性?

时间:2011-07-05 18:48:55

标签: c# entity-framework

我是Entity Framework的新手(以前主要使用NHibernate和ActiveRecord)而且我遇到了一些问题,我觉得应该很容易......

我有一个User实体,并创建了部分User类,所以我可以添加一些方法(比如NHibernate)。我添加了GetByID以便让用户更轻松:

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

现在在同一个班级我想记录登录的时刻,我试着这样做:

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();
    }
}

问题是我无法访问user.LoginLogs,因为已经处理了user's上下文...很可能我在这里遗漏了一些明显的内容,但总是创建完整的查询,如:

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

似乎不是一个好选择...

我已经阅读了关于存储库模式的内容,但我认为这对于此类任务来说太过大了。请解释一下我做错了什么。提前谢谢!

修改

描绘我想做的事情:

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

通常情况下,我不允许这样做,因为没有上下文我无法获得post.Answers ...

2 个答案:

答案 0 :(得分:1)

您正在关闭对象上下文,然后尝试将日志添加到已分离的用户。您需要附加用户,以便objectContext知道已更改或添加的内容。

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();
    }
}

更新
您也可以附加该对象。

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();
    }
}

更新

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

注意如果LoginLogs是另一个表,则需要使用Include。

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

答案 1 :(得分:0)

如果您愿意使用存储过程(并且它们与EF协同工作),您可以返回用户对象并同时通过一次调用数据库添加到日志表中。

我曾经在EF / ORM之前的日子里做过SP的所有事情,当我去EF时我非常努力地避免使用存储过程来避免重新回到我的旧习惯,但现在我发现有选择性使用存储过程,您既可以享受EF的工作方式,也可以获得写得很好的SP可以提供的超级功能/性能。