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

时间:2016-04-05 04:46:43

标签: entity-framework ef-code-first linq-to-entities projection

我首先使用实体​​框架从代码创建数据库外键时遇到问题。查询下面的表格,并将数据投影到另一个模型中,如下所示。一切似乎都是正确的,虽然当我查询数据时,AddressId的联接列似乎不起作用,而我的" Street"列返回空白数据。

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; } 
    }

}

我的第二个表包含已加入的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();

1 个答案:

答案 0 :(得分:1)

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

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!
             });

此查询将不返回Persons,而是返回包含Person的信息的地址。如果你想带人的地址,你应该按操作分组,并留下外连接以保存没有地址的人:

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
              });