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