Entity Framework 多对多 - 无法获取数据
Entity Framework Many to Many - Cannot get data
我在现有的两个 table 之间引入了多对多关系。为此,我添加了第三个 table,其中仅包含其他两个 table 的 ID。
因为我用的是EF,所以我也加了
public virtual List<EntityOne> EntityOnes
在 EntityTwo
和
public virtual List<EntityTwo> EntityTwos
在 EntityOne 中。
但是,有了这个,当我得到 EntityTwo 对象时,它不包含关联的 EntityOne 对象。该列表的计数为零,即使数据在 table 中。
我是不是漏掉了什么?还有什么需要我做的吗?
不确定,如果这是相关的,但我在 OnModelCreation 中也有这个
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EntityOne>().
HasMany(p => p.EntityTwos).
WithMany(a => a.EntityOnes).
Map(
m =>
{
m.MapLeftKey("EntityTwoId");
m.MapRightKey("EntityOneId");
m.ToTable("EntityRelations");
});
////Make sure a context is not created by default.
}
试试这个:
public partial class One
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
private ICollection<OneTwo> _oneTwos;
public virtual ICollection<OneTwo> OneTwos
{
get { return _oneTwos ?? (_oneTwos = new List<OneTwo>()); }
set { _oneTwos = value; }
}
}
public partial class Two
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
private ICollection<OneTwo> _oneTwos;
public virtual ICollection<OneTwo> OneTwos
{
get { return _oneTwos ?? (_oneTwos = new List<OneTwo>()); }
set { _oneTwos = value; }
}
}
将导航属性添加到连接 class:
public partial class OneTwo
{
public virtual int OneId { get; set; }
public virtual int TwoId { get; set; }
public virtual One One { get; set; }
public virtual Two Two { get; set; }
}
将复合键添加到联接 class 并配置关系:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<OneTwo>() // composite primary key
.HasKey(p => new { p.OneId, p.TwoId });
modelBuilder.Entity<OneTwo>()
.HasRequired(a => a.One)
.WithMany(c => c.OneTwos)
.HasForeignKey(fk => fk.OneId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<OneTwo>()
.HasRequired(a => a.Two)
.WithMany(c => c.OneTwos)
.HasForeignKey(fk => fk.TwoId)
.WillCascadeOnDelete(false);
// TODO: handle orphans when last asociation is deleted
}
另一种策略是通过 EntityTypeConfiguration<> 配置 EF 关系。以下多对多关系实现演示了该方法:
City.cs
public partial class City
{
public virtual int Id { get; set; }
private ICollection<CountyCity> _countiesCities;
public virtual ICollection<CountyCity> CountiesCities
{
get { return _countiesCities ?? (_countiesCities = new List<CountyCity>()); }
set { _countiesCities = value; }
}
}
County.cs
public partial class County
{
public virtual int Id { get; set; }
private ICollection<CountyCity> _countiesCities;
public virtual ICollection<CountyCity> CountiesCities
{
get { return _countiesCities ?? (_countiesCities = new List<CountyCity>()); }
set { _countiesCities = value; }
}
}
县City.cs
public partial class CountyCity
{
public virtual int CountyId { get; set; }
public virtual int CityId { get; set; }
public virtual County County { get; set; }
public virtual City City { get; set; }
}
CountyCityConfiguration.cs(EF 6 实现)
public class CountyCityConfiguration : IEntityTypeConfiguration<CountyCity>
{
public void Map(EntityTypeBuilder<CountyCity> builder)
{
// Table and Schema Name declarations are optional
//ToTable("CountyCity", "dbo");
// composite primary key
builder.HasKey(p => new { p.CountyId, p.CityId });
builder.HasOne(pt => pt.County)
.WithMany(p => p.CountiesCities)
.HasForeignKey(pt => pt.CountyId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(pt => pt.City)
.WithMany(t => t.CountiesCities)
.HasForeignKey(pt => pt.CityId)
.OnDelete(DeleteBehavior.Restrict);
// TODO: handle orphans when last association is deleted
}
}
Entity Framework 6 个实现:
您可以使用 EntityTypeConfiguration<> 配置复合键和关系,如前面的代码所示。
Entity Framework 核心实现:
EntityTypeConfiguration<> 尚未迁移。但是,它在下一个版本的路线图上。
在此期间,您可以使用temporary pattern suggested by the EF team, or one of the patterns discussed this rather lengthy Whosebug post discussing entity configuration in Entity Framework 7。
我在阅读 EF 团队 post 之前的冗长讨论中实现了由 Cocowalla 编写的模式 post。 source code for my workaround is available in this GitHub repository.
IEntityTypeConfiguration.cs
namespace Dna.NetCore.Core.DAL.EFCore.Configuration.Temporary.Cocowalla
{
// attribute:
public interface IEntityTypeConfiguration<TEntityType> where TEntityType : class
{
void Map(EntityTypeBuilder<TEntityType> builder);
}
}
这是我对该模式的实现:
namespace Dna.NetCore.Core.DAL.EFCore.Configuration.Common
{
public class StateOrProvinceConfiguration : IEntityTypeConfiguration<StateOrProvince>
{
public void Map(EntityTypeBuilder<StateOrProvince> builder)
{
// EF Core
builder.HasOne(p => p.Country).WithMany(p => p.StateOrProvinces).HasForeignKey(s => s.CountryId).OnDelete(DeleteBehavior.Cascade);
builder.HasMany(d => d.Cities).WithOne().OnDelete(DeleteBehavior.Cascade);
builder.HasMany(d => d.Counties).WithOne().OnDelete(DeleteBehavior.Cascade);
}
}
}
我在现有的两个 table 之间引入了多对多关系。为此,我添加了第三个 table,其中仅包含其他两个 table 的 ID。
因为我用的是EF,所以我也加了
public virtual List<EntityOne> EntityOnes
在 EntityTwo
和
public virtual List<EntityTwo> EntityTwos
在 EntityOne 中。
但是,有了这个,当我得到 EntityTwo 对象时,它不包含关联的 EntityOne 对象。该列表的计数为零,即使数据在 table 中。
我是不是漏掉了什么?还有什么需要我做的吗?
不确定,如果这是相关的,但我在 OnModelCreation 中也有这个
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EntityOne>().
HasMany(p => p.EntityTwos).
WithMany(a => a.EntityOnes).
Map(
m =>
{
m.MapLeftKey("EntityTwoId");
m.MapRightKey("EntityOneId");
m.ToTable("EntityRelations");
});
////Make sure a context is not created by default.
}
试试这个:
public partial class One
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
private ICollection<OneTwo> _oneTwos;
public virtual ICollection<OneTwo> OneTwos
{
get { return _oneTwos ?? (_oneTwos = new List<OneTwo>()); }
set { _oneTwos = value; }
}
}
public partial class Two
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
private ICollection<OneTwo> _oneTwos;
public virtual ICollection<OneTwo> OneTwos
{
get { return _oneTwos ?? (_oneTwos = new List<OneTwo>()); }
set { _oneTwos = value; }
}
}
将导航属性添加到连接 class:
public partial class OneTwo
{
public virtual int OneId { get; set; }
public virtual int TwoId { get; set; }
public virtual One One { get; set; }
public virtual Two Two { get; set; }
}
将复合键添加到联接 class 并配置关系:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<OneTwo>() // composite primary key
.HasKey(p => new { p.OneId, p.TwoId });
modelBuilder.Entity<OneTwo>()
.HasRequired(a => a.One)
.WithMany(c => c.OneTwos)
.HasForeignKey(fk => fk.OneId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<OneTwo>()
.HasRequired(a => a.Two)
.WithMany(c => c.OneTwos)
.HasForeignKey(fk => fk.TwoId)
.WillCascadeOnDelete(false);
// TODO: handle orphans when last asociation is deleted
}
另一种策略是通过 EntityTypeConfiguration<> 配置 EF 关系。以下多对多关系实现演示了该方法:
City.cs
public partial class City
{
public virtual int Id { get; set; }
private ICollection<CountyCity> _countiesCities;
public virtual ICollection<CountyCity> CountiesCities
{
get { return _countiesCities ?? (_countiesCities = new List<CountyCity>()); }
set { _countiesCities = value; }
}
}
County.cs
public partial class County
{
public virtual int Id { get; set; }
private ICollection<CountyCity> _countiesCities;
public virtual ICollection<CountyCity> CountiesCities
{
get { return _countiesCities ?? (_countiesCities = new List<CountyCity>()); }
set { _countiesCities = value; }
}
}
县City.cs
public partial class CountyCity
{
public virtual int CountyId { get; set; }
public virtual int CityId { get; set; }
public virtual County County { get; set; }
public virtual City City { get; set; }
}
CountyCityConfiguration.cs(EF 6 实现)
public class CountyCityConfiguration : IEntityTypeConfiguration<CountyCity>
{
public void Map(EntityTypeBuilder<CountyCity> builder)
{
// Table and Schema Name declarations are optional
//ToTable("CountyCity", "dbo");
// composite primary key
builder.HasKey(p => new { p.CountyId, p.CityId });
builder.HasOne(pt => pt.County)
.WithMany(p => p.CountiesCities)
.HasForeignKey(pt => pt.CountyId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(pt => pt.City)
.WithMany(t => t.CountiesCities)
.HasForeignKey(pt => pt.CityId)
.OnDelete(DeleteBehavior.Restrict);
// TODO: handle orphans when last association is deleted
}
}
Entity Framework 6 个实现:
您可以使用 EntityTypeConfiguration<> 配置复合键和关系,如前面的代码所示。
Entity Framework 核心实现:
EntityTypeConfiguration<> 尚未迁移。但是,它在下一个版本的路线图上。
在此期间,您可以使用temporary pattern suggested by the EF team, or one of the patterns discussed this rather lengthy Whosebug post discussing entity configuration in Entity Framework 7。
我在阅读 EF 团队 post 之前的冗长讨论中实现了由 Cocowalla 编写的模式 post。 source code for my workaround is available in this GitHub repository.
IEntityTypeConfiguration.cs
namespace Dna.NetCore.Core.DAL.EFCore.Configuration.Temporary.Cocowalla
{
// attribute:
public interface IEntityTypeConfiguration<TEntityType> where TEntityType : class
{
void Map(EntityTypeBuilder<TEntityType> builder);
}
}
这是我对该模式的实现:
namespace Dna.NetCore.Core.DAL.EFCore.Configuration.Common
{
public class StateOrProvinceConfiguration : IEntityTypeConfiguration<StateOrProvince>
{
public void Map(EntityTypeBuilder<StateOrProvince> builder)
{
// EF Core
builder.HasOne(p => p.Country).WithMany(p => p.StateOrProvinces).HasForeignKey(s => s.CountryId).OnDelete(DeleteBehavior.Cascade);
builder.HasMany(d => d.Cities).WithOne().OnDelete(DeleteBehavior.Cascade);
builder.HasMany(d => d.Counties).WithOne().OnDelete(DeleteBehavior.Cascade);
}
}
}