未加载可选的导航属性

时间:2011-11-08 17:27:24

标签: c# linq-to-entities entity-framework-4.1 lazy-loading

我不能为我的生活弄清楚为什么Entity Framework(4.1,Code First)没有实现可选的导航属性。

波苏斯:

public class PlanMember {
    public Int64 Id { get; set; }

    public String FirstName { get; set; }

    public virtual SystemUser CaseManager { get; set; }

    public String LastName { get; set; }

    public virtual PlanMemberStatus Status { get; set; }
}

public class SystemUser {
    public String EMail { get; set; }

    public String FirstName { get; set; }

    public String Id { get; set; }

    public String LastName { get; set; }
}

public class PlanMemberStatus {
    public Int32 Id { get; set; }

    public String Code { get; set; }
}

配置类:

public class ForPlanMemberEntities:EntityTypeConfiguration<PlanMember> {
    public ForPlanMemberEntities(String schemaName) {
        this.HasOptional(e => e.CaseManager)
            .WithMany()
            .Map(m => m.MapKey("CaseManagerID"));
        this.HasRequired(e => e.Status)
            .WithMany()
            .Map(m => m.MapKey("StatusID"));
        this.ToTable("PlanMember", schemaName);
    }
}

public class ForSystemUserEntities:EntityTypeConfiguration<SystemUser> {
    public ForSystemUserEntities(String schemaName) {
        this.ToTable("SystemUser", schemaName);
    }
}

public class ForPlanMemberStatusEntities:EntityTypeConfiguration<PlanMemberStatus> {
    public ForPlanMemberStatusEntities(String schemaName) {
        this.ToTable("PlanMemberStatus", schemaName);
    }
}

上下文

public class Context:DbContext {
    public DbSet<PlanMember> PlanMemberDbSet { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        var schemaName = Properties.Settings.Default.SchemaName;
        modelBuilder.Configurations
            .Add(new Configuration.ForPlanMemberEntities(schemaName))
            .Add(new Configuration.ForPlanMemberStatusEntities(schemaName))
            .Add(new Configuration.ForSystemUserEntities(schemaName))
            ;
    }
}

根据该配置,如果我运行如下的查询,它将不会填充CaseManager属性。 PlanMemberStatus属性加载得很好。

var test = (from member in PlanMemberDbSet
            where member.CaseManager != null
            select member).First();
var cm = test.CaseManager;

在我的示例中,cm总是null,尽管从逻辑上讲这是不可能的。有什么想法吗?

编辑 - 如果我执行PlanMemberDbSet.Include("CaseManager"),那么它会按预期工作。为什么这有必要?在其他情况下,我没有必要这样做。

1 个答案:

答案 0 :(得分:1)

我的猜测是CaseManagerID表中的PlanMember外键列值与表Id中的SystemUser主键列值不同 - .NET不同但不适用于SQL Server(使用标准排序系统),例如外壳不同:CaseManagerID中的“ a ”,{{1}中的“ A ” }。

查询Id(转换为SQL中的!= null)有效,因此您确实只获得了在数据库中分配了IS NOT NULL的{​​{1}}个实体。此外,PlanMember的查询(由延迟加载触发)在数据库(INNER JOIN)中正确执行并传输到客户端。甚至对象实现也起作用(上下文中有2个对象)。但是EF无法将加载的SystemUser与加载的CaseManager相关联,因为密钥不相同(例如,关于大写/小写字母)。因此,您的导航属性为PlanMember

CaseManager导航属性不会发生这种情况,因为密钥是null

问题与此问题密切相关:EF 4.1 Code First bug in Find/Update. Any workaround? Should it be reported?