2015-04-12 79 views
1

我有流利的API和实体框架(关系多对多)的问题。当我试图从数据库中获取数据时,在对象CompanypkdClassification上有空值。价值CompanyIdPkdClassyficationId正常返回。实体框架CodeFirst多对多返回对象null

上下文

//in contrstructor set 
// this.Configuration.LazyLoadingEnabled = true; 

     .Entity<CompanyPkdClassification>() 
     (c => new { c.PkdClassyficationId, c.CompanyId }); 

     modelBuilder.Entity<Company>() 
      .HasMany(c => c.companyPkdClassification) 
      .WithRequired() 
      .HasForeignKey(c => c.CompanyId); 

     modelBuilder.Entity<PkdClassification>() 
      .HasMany(c => c.companyPkdClassification) 
      .WithRequired() 
      .HasForeignKey(c => c.PkdClassyficationId);} 

pkdClassification

public class PkdClassification 
{ 
    [Key] 
    [DisplayName("Id")] 
    public int id { get; set; } 
    ... 
    public virtual ICollection<CompanyPkdClassification> companyPkdClassification { get; set; } 
} 

companyPkdClassification

public class CompanyPkdClassification 
{ 
    [ForeignKey("company")] 
    public int CompanyId { get; set; } 

    [ForeignKey("pkdClassification")] 
    public int PkdClassyficationId { get; set; } 

    public virtual ICollection<Company> company { get; set; } 
    public virtual ICollection<PkdClassification> pkdClassification { get; set; } 
} 

而最后一个公司

public class Company : baseModel 
{ 
    ... 
virtual ICollection<CompanyPkdClassification> companyPkdClassification { get; set; } 


} 

回答

2

映射在代码中首先一个多一对多的关系,最好的办法是这样的:

public class Classification 
{ 
    [Key] 
    [DisplayName("Id")] 
    public int id { get; set; } 
    ... 
    public virtual ICollection<Company> Companies{ get; set; } 
} 

public class Company 
{ 
    public int Id { get; set; } 
    ... 
    public virtual ICollection<Classification> Classifications { get; set; } 
} 

默认情况下,代码首先将创建一个第三结合表,ClassificationCompanies其中将包括PK两个表,即。 ClassificationId & CompanyId

如果需要指定结点表和FK列的名字,那么你可以配置的关系,覆盖在你的上下文OnModelCreating方法的使用流利的API:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 

    modelBuilder.Entity<Classification>() 
       .HasMany<Company>(s => s.Companies) 
       .WithMany(c => c.Classifications) 
       .Map(cs => 
         { 
          cs.MapLeftKey("ClassificationId"); 
          cs.MapRightKey("CompanyId"); 
          cs.ToTable("ClassificationCourses"); 
         }); 

} 

另一种方法是创建一个代表联结表的实体(如您试图执行的),并建立与ClassificationCompany的两个一对多关系,但如果您不需要向联结表添加额外的列,则建议使用第一个变体。如果按照这个变型,实体代表结合表会是这样:

public class CompanyPkdClassification 
{ 
    public int CompanyId { get; set; } 

    public int PkdClassyficationId { get; set; } 

    public virtual Company Company { get; set; } 
    public virtual Classification Classification { get; set; } 
} 

而且配置:

 modelBuilder.Entity<CompanyPkdClassification>().HasKey(c => new { c.PkdClassyficationId, c.CompanyId }); 

    modelBuilder.Entity<Company>() 
     .HasMany(c => c.companyPkdClassification) 
     .WithRequired(cc=>Company) 
     .HasForeignKey(c => c.CompanyId); 

    modelBuilder.Entity<PkdClassification>() 
     .HasMany(c => c.companyPkdClassification) 
     .WithRequired(cc=>Classification) 
     .HasForeignKey(c => c.PkdClassyficationId);} 
+0

我选择了第二个变体,它的功能非常完美。非常感谢 :) – michal

1

你能证明你正在使用得到的值查询?我认为这将与被加载的对象有关。如果您在请求导航属性之前执行了ToList(),那么这些值将为空。你必须在你的查询中添加这种要么强制值包括:

.Include(x => x.Company) 

等为每个对象你想要或要求值,而该对象是否仍然活着。即在执行ToList()之前;在此处更详细地解释:https://msdn.microsoft.com/en-gb/library/vstudio/bb738633%28v=vs.100%29.aspx

根据您的评论,FirstOrDefault()将执行查询,因此不能再在此点之后填充导航属性。我会试试这个(提供dbContext.company是一组公司对象):

添加使用System.Data.Entity;

public Company getCompany(int id) { 
    Company data = dbContext.company.Include(x => x.companyPkdClassification .Select(y => y.company)).Include(x => x.companyPkdClassification .Select(y => y.pkdClassification)).Where(i => i.id == id).FirstOrDefault(); 
    return data; 
} 
+0

只是简单: 'code' 上市公司getCompany(INT ID ) { Company data = dbContext.company 。Where(i => i.id == id) .FirstOrDefault(); 返回数据; } 'code' – michal

+0

不错,谢谢Dhunt! – DigaoParceiro