EF Code First:添加外键关系Linq-to-Entity投影

EF Code First: Add a Foreign Key relationship Linq-to-Entity projection

我在使用 entity framework 从代码创建数据库外键方面遇到了问题。下面显示的 tables 被查询,数据被投影到另一个模型中,如下所示。一切似乎都是正确的,尽管当我查询数据时,通过 AddressId 连接的列似乎没有工作并且我的 "Street" 列 returns 空白数据。

namespace Mvc4Connect.ViewModels
{

[Table("PersonEntity")]
public class PersonEntity : EntityTypeConfiguration<PersonEntity>
    {
    //Constructor
    public PersonEntity()
    {
        this.ToTable("TB008555", schemaName: "SchemaUser");
        this.Property(c => c.PersonId).HasColumnName("CL005500");
        this.Property(c => c.FirstName).HasColumnName("CL005545");
        this.Property(c => c.LastName).HasColumnName("CL005550");
        this.Property(c => c.AddressId).HasColumnName("CL044760");
    }


    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int PersonId { get; set; }
    public String FirstName { get; set; } //firstname
    public String LastName { get; set; } //lastname

    [ForeignKey("AddressEntity")]
    public int AddressId { get; set; }

    public virtual ICollection<AddressEntity> AddressEntity { get; set; } 
    }

}

我的第二个 table 包含加入的 AddressId

namespace Mvc4Connect.ViewModels
{

[Table("AddressEntity")]
public class AddressEntity : EntityTypeConfiguration<AddressEntity>
{
    //Constructor
    public AddressEntity()
    {

        this.ToTable("TB047697", schemaName: "SchemaUser");
        this.Property(c => c.AddressId).HasColumnName("CL045695");
        this.Property(c => c.Street).HasColumnName("CL042710");
        this.Property(c => c.City).HasColumnName("CL044747");
        this.Property(c => c.State).HasColumnName("CL047460");
    }

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int AddressId { get; set; }
    public string Street { get; set; }        
    public string City { get; set; }
    public string State { get; set; }

}

}

我的实体上下文

public class EntityContext : DbContext
{
public DbSet<PersonEntity> Persons { get; set; }
public DbSet<AddressEntity> Address { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        modelBuilder.Configurations.Add(new PersonEntity());
        modelBuilder.Configurations.Add(new AddressEntity());
}
}

这是我试图在我的 API 控制器中使用的查询。

var dbv = new EntityContext(); 

var query = (from vt in dbv.Persons
                   from ad in dbv.Address
                   where vt.LastName.StartsWith(ln)
                   where vt.FirstName.StartsWith(fn) 
                   where ad.AddressId == vt.AddressId
                   select new PersonVM() // Create new object for projection
                   {
                       PersonId = vt.PersonId,
                       FirstName = vt.FirstName,
                       LastName = vt.LastName,
                       Street = ad.Street, // Blank Street data
                       AddressId = vt.AddressId // Debug to assure Id is assigned
                   });

        return query.ToList();

我认为您在确定表之间的关系时犯了错误:组合:

public class PersonEntity : EntityTypeConfiguration<PersonEntity>
{
    [ForeignKey("AddressEntity")]
    public int AddressId { get; set; }    
    public virtual ICollection<AddressEntity> AddressEntity { get; set; } 
    //other properties...
}

不正确!相反,如果 Person 和 Address 之间的关系是一对多的,你应该这样写:

public class PersonEntity : EntityTypeConfiguration<PersonEntity>
{
    //[ForeignKey("AddressEntity")]
    //public int AddressId { get; set; }    
    public virtual ICollection<AddressEntity> AddressEntity { get; set; } 
    //other properties...
}

public class AddressEntity : EntityTypeConfiguration<AddressEntity>
{
     [ForeignKey("Person")]
     public int PersonId { get; set; }
     public virtual PersonEntity Person { get; set; }
     //other properties...
}

最终查询将如下所示:

var query = (from vt in dbv.Persons
             from ad in dbv.Address
             where vt.LastName.StartsWith(ln)
             where vt.FirstName.StartsWith(fn) 
             where vt.PersonId == ad.PersonId//this line was changed!
             select new PersonVM
             {
                 vt.PersonId,
                 vt.FirstName,
                 vt.LastName,
                 ad.Street,
                 ad.AddressId //this line was changed!
             });

此查询将 return 不是人,而是包含关于人的信息的地址。如果你想把人带上他们的地址,你应该执行 group by 操作,同时左外连接来保存没有地址的人:

var query = (from vt in dbv.Persons                     
             where vt.LastName.StartsWith(ln)
             where vt.FirstName.StartsWith(fn)
             join ad in dbv.Address on vt.PersonId equals ad.PersonId into subAddresses
             from subAdr in subAddresses.DefaultIfEmpty()
             group subAdr by new { vt.PersonId, vt.FirstName, vt.LastName } into groupPers                                          
             select new
             {
                  groupPers.Key.PersonId,
                  groupPers.Key.FirstName,
                  groupPers.Key.LastName,
                  addresses = groupPers
              });