2011-11-08 45 views
1

我不能为我的生活弄清楚为什么实体框架(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)) 
      ; 
    } 
} 

基础上的conf配置,如果我运行如下查询它不会填充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

我的猜测是,在PlanMemberCaseManagerID外键列值在表SystemUser不同的Id主键列值 - 为.NET不同,但不能用于SQL Server(标准分拣系统),例如不同在外壳中:“a”in CaseManagerID,but“A”in Id

查询!= null(转化为IS NOT NULL在SQL)的作品,让您得到确实只有PlanMember实体具有分配在数据库中SystemUser。另外由CaseManager(由延迟加载触发)的查询在数据库(INNER JOIN)中正确执行并传输到客户端。即使是对象实现也是如此(上下文中有2个对象)。但EF未能将加载的PlanMember与加载的CaseManager相关联,因为这些密钥不相同(例如关于大写/小写字母)。因此导航属性为null

这与Status导航属性不会发生,因为密钥是Int32

问题看起来与之密切相关的一个:EF 4.1 Code First bug in Find/Update. Any workaround? Should it be reported?

+0

你的第一段是100%正确的。 'PlanMember'表的值都是大写的,'SystemUser'表的值都是小写的。一旦我把它们变成两个相同的情况,它就会神奇地起作用。绝对是一个错误,国际海事组织。 – Yuck