延迟加载在EntityFramework 6中不起作用

时间:2015-04-07 14:02:00

标签: c# entity-framework lazy-loading

我已将以下属性设为true。

Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;

我有两个班级:

 public partial class User : BaseEntity
    {
        public User()
        {
            this.UserRoles = new List<UserRole>();
        }

        public int UserId { get; set; }
        public string FirstName { get; set; }
        public virtual ICollection<UserRole> UserRoles { get; set; }
    }

public partial class UserRole : BaseEntity
    {
        public int UserRoleId { get; set; }
        public int UserId { get; set; }
        public int RoleId { get; set; }
        public virtual User User { get; set; }
    }

我正在从EF 6调用存储过程,如下所示:

public IEnumerable<User> GetUserDetails(int? userId)
{
    var userIDParameter = userId.HasValue ?
    new SqlParameter("@UserId", userId) :
    new SqlParameter("@UserId", typeof(int));
    return _dbContext.Database
        .SqlQuery<User>("usp_GetUserDetails @UserId", userIDParameter);
}

在Controller中调用如下:

IEnumerable<User> user =  _storedProcedureService.GetUserDetails(5);

在我的SP中,我的逻辑是:

Select * from User where UserId = @UserId

我获得与User相关的所有数据,但UserRoles.Count为零。

我做错了什么?

4 个答案:

答案 0 :(得分:4)

在使用ADO.NET时,您询问是否使用了与实体框架的延迟加载。 ADO.NET不支持Lazy Loading,实体框架。

您的信息是ADO.NET;

var userIDParameter = userId.HasValue ?
                new SqlParameter("@UserId", userId) :
                new SqlParameter("@UserId", typeof(int));
return  _dbContext.Database.SqlQuery<User>("usp_GetUserDetails @UserId", userIDParameter);

使用SqlParameter之类的东西。

这是实体框架;

using (var db = new MyContext())
{
    return db.User.Single(u => u.UserId = id);
}

或者,使用存储过程;

using (var db = new MyContext())
{
    return db.GetUserDetails(id);
}

如果您想让Entity Framework处理存储过程支持延迟加载,我建议您关注this tutorial

答案 1 :(得分:1)

到目前为止,答案完全错过了标记。说实体框架方法context.Database.SqlQuery<T>)绕过实体框架或它是纯粹的ADO.Net是不正确的。

您使用SqlQuery<T>。这与数据库优先方法不同,后者将存储过程导入EDMX。导入的存储过程由不同的方法执行:ExecuteFunction。调用此方法并将结果映射到实体类型时,会发生在执行context.Database.SqlQuery<T>时不会发生的两件事。

  1. 实体由上下文的更改跟踪器跟踪。
  2. 实体执行延迟加载。
  3. 好的,两种不同的方法呈现不同的行为,为什么不呢?我可以忍受这个。唯一的事情(并且答案忽略了这一事实)是context.Database.SqlQuery<T>T是实体类型时返回动态代理。 动态代理应该执行延迟加载。这是它所做的事情之一。所以对我来说意外的是,这两个陈述不会产生相同的结果:

    var roles1 = _dbContext.Database.SqlQuery<User>(...).First().UserRoles;
    var roles2 = _dbContext.Users.AsNoTracking().First(u => u.UserId == x).UserRoles;
    

    只有第二个语句执行延迟加载,但都创建了一个代理User实体。也许这是设计的。即便如此, 仍然令人困惑。

答案 2 :(得分:0)

您正在使用存储过程来检索绕过所有Entity Framework的用户对象,您将需要使用Entity Framework来检索您的用户以使Entity Framework完成其工作。如下所示。

_context.Set<Users>().Single(u=>u.UserId=5)

答案 3 :(得分:0)

原帖是正确的。 SQLQuery是一个EF方法,但它不返回支持延迟加载的对象。由于它使用反射将所选列返回到对象中,因此甚至可能无法设置对象键。在这种情况下,无法识别子对象。返回的对象不能像object.Parent.ID或object.Children.Count()一样使用。