C# 实体上未加载关联属性

C# 实体上未加载关联属性,c#,.net,entity-framework,C#,.net,Entity Framework,我有三个相关实体,最好用这个图来描述: 当我加载用户时,使用以下代码加载用户对象,即不为null,但是用户对象上的角色和部门属性为null,尽管用户数据库记录具有这些关联的有效FK值 using (var productionEntities = new ProductionEntities()) { var userName = GetUserName(); User u = (from usr in productionEntities.UserSet

我有三个相关实体,最好用这个图来描述:

当我加载用户时,使用以下代码加载
用户
对象,即不为null,但是
用户
对象上的
角色
部门
属性为null,尽管用户数据库记录具有这些关联的有效FK值

using (var productionEntities = new ProductionEntities())
{
    var userName = GetUserName();
    User u = (from usr in productionEntities.UserSet
              where usr.UserName == userName
              select usr).FirstOrDefault();
    if (u == null)
    {
        throw new KpiSecurityException("No local database entry found for user.") { UserName = userName };
    }
    return u.Department.DeptName;
}

旁白:我完成了整个任务,只是因为ASP.NET MembershipProvider不支持像department这样的用户“元数据”,而且我还必须使用ProfileProvider,代价是巨大的数据库膨胀。

您必须显式加载此属性

User u = (from usr in productionEntities.UserSet
          where usr.UserName == userName
          select usr).FirstOrDefault();

if (u == null)
{
        throw new KpiSecurityException("No local database entry found for user.") { UserName = userName };
}

if (!u.RoleReference.IsLoaded)
{ u.RoleReference.Load(); }

if (!u.DeparmentReference.IsLoaded)
{ u.DeparmentReference.Load(); }
或者在查询中包含此实体

User u = (from usr in productionEntities.UserSet.Include("Role").Include("Department")
          where usr.UserName == userName
          select usr).FirstOrDefault();

必须显式加载此属性

User u = (from usr in productionEntities.UserSet
          where usr.UserName == userName
          select usr).FirstOrDefault();

if (u == null)
{
        throw new KpiSecurityException("No local database entry found for user.") { UserName = userName };
}

if (!u.RoleReference.IsLoaded)
{ u.RoleReference.Load(); }

if (!u.DeparmentReference.IsLoaded)
{ u.DeparmentReference.Load(); }
或者在查询中包含此实体

User u = (from usr in productionEntities.UserSet.Include("Role").Include("Department")
          where usr.UserName == userName
          select usr).FirstOrDefault();

既然你只需要部门名称,那就这样吧;这样,您只能查询数据库一次:

using (var productionEntities = new ProductionEntities())
{
    var userName = GetUserName();
    var u  = (from usr in productionEntities.UserSet
              where usr.UserName == userName
              select new
              {
                  DeptName = usr.Department.DeptName
              }).FirstOrDefault();
    if (u == null)
    {
        throw new KpiSecurityException("No local database entry found for user.") { UserName = userName };
    }
    return u.DeptName;
}

既然你只需要部门名称,那就这样吧;这样,您只能查询数据库一次:

using (var productionEntities = new ProductionEntities())
{
    var userName = GetUserName();
    var u  = (from usr in productionEntities.UserSet
              where usr.UserName == userName
              select new
              {
                  DeptName = usr.Department.DeptName
              }).FirstOrDefault();
    if (u == null)
    {
        throw new KpiSecurityException("No local database entry found for user.") { UserName = userName };
    }
    return u.DeptName;
}

这将导致三个DB查询;只需要一个。+1用于教我IsLoaded和Load()成员。我知道有类似的东西,但我只是不知道在哪里可以找到它。Ishtar,
Load()
生成了太多的查询,
Include
生成了过于复杂的查询。无论是哪种方式,都会使数据库服务器的工作变得比返回单个字段更困难。克雷格:但问题是加载引用的属性,而不是选择单个字段。在LINQ中,实体并不是实现这一点的另一种正确方法。使用存储过程列出和选择将适得其反。他的方法返回一个字段。为什么还要选择其他东西呢。没有人建议存储进程;那将是浪费精力。L2E已经处理好了。我不知道为什么要执行一个查询(或多个查询!),当您只需要从方法返回一个值时,它会从多个对象返回几十个属性;只需要一个。+1用于教我IsLoaded和Load()成员。我知道有类似的东西,但我只是不知道在哪里可以找到它。Ishtar,
Load()
生成了太多的查询,
Include
生成了过于复杂的查询。无论是哪种方式,都会使数据库服务器的工作变得比返回单个字段更困难。克雷格:但问题是加载引用的属性,而不是选择单个字段。在LINQ中,实体并不是实现这一点的另一种正确方法。使用存储过程列出和选择将适得其反。他的方法返回一个字段。为什么还要选择其他东西呢。没有人建议存储进程;那将是浪费精力。L2E已经处理好了。我不知道为什么要执行一个查询(或多个查询!),当您只需要从该方法返回一个值时,它会从多个对象返回几十个属性。