无法查询多对多关系

时间:2016-10-28 09:15:45

标签: c# entity-framework entity-framework-core

是否有人知道如何在EF Core中查询DB以获得多对多关系,但更像是从一侧留下外部联接?

让我解释一下我的意思。

Currency.cs

public class Currency
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid UID { get; set; } = Guid.NewGuid();

    public string   ISOCode { get; set; }

    public string   Symbol  { get; set; }

    [JsonIgnore]
    public List<RegionCurrency> RegionCurrencies { get; set; }
}

RegionCurrency.cs

public class RegionCurrency
{
    public Guid CurrencyUID { get; set; }

    public Guid RegionUID { get; set; }

    [ForeignKey("CurrencyUID")]
    public Currency Currency { get; set; }

    [ForeignKey("RegionUID")]
    public Region Region { get; set; }
}

Region.cs

public class Region
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid     UID { get; set; } = Guid.NewGuid();

    [StringLength(8)]
    public string CountryISOCode         { get; set; }

    public List<RegionCurrency> RegionCurrencies { get; set; }
}

MyContext.cs

public class LookupTablesContext : DbContext
{
    public virtual DbSet<Currency> Currecies { get; set; }

    public virtual DbSet<RegionCurrency> RegionCurrency { get; set; }

    public virtual DbSet<Region> Regions { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.HasDefaultSchema(SchemaName);

        modelBuilder.Entity<RegionCurrency>()
            .HasKey(t => new { t.CurrencyUID, t.RegionUID })
            .HasName("PK_RegionCurrency");

        modelBuilder.Entity<RegionCurrency>()
            .HasOne(pt => pt.Region)
            .WithMany(p => p.RegionCurrencies)
            .HasForeignKey(pt => pt.RegionUID);

        modelBuilder.Entity<RegionCurrency>()
            .HasOne(pt => pt.Currency)
            .WithMany(p => p.RegionCurrencies)
            .HasForeignKey(pt => pt.CurrencyUID);

        modelBuilder.Entity<Currency>()
            .HasIndex(c => c.ISOCode)
            .HasName("UX_Currency_ISOCode")
            .IsUnique();

        modelBuilder.Entity<Region>()
            .HasIndex(c => c.CountryISOCode)
            .HasName("UX_Region_CountryISOCode")
            .IsUnique();
    }
}

我的查询:

var result = ctx.Currencies
                  .Include(c => c.RegionCurrencies)
                  .ThenInclude(rc => rc.Select(rcs => rcs.Regions)) // This seems to be wrong
            .SingleOrDefault(c => c.ISOCode == "EUR");

我也尝试使用包含,如下图所示:

many-to-many relationship include

请注意,RegionCurrencies表可以包含0-N关系,我想获得Currency实体,即使RegionCurrency表中没有记录。

这个(和类似的尝试)最终出现在这样的异常中:

类型&#39; System.ArgumentException&#39;的例外情况发生在Microsoft.EntityFrameworkCore.dll中但未在用户代码中处理

附加信息:属性表达式&#39; rc =&gt; {来自RegionCurrency rc in rcs select [pts] .Regions}&#39;无效。表达式应代表属性访问权限:&#39; t =&gt; t.MyProperty&#39 ;.有关包含相关数据的更多信息,请参阅http://go.microsoft.com/fwlink/?LinkID=746393

Dependencies:
"Microsoft.EntityFrameworkCore": "1.0.1",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",

我找不到任何有效的例子。但当然我只是失明。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

您可以按照以下所示进行操作。

var tag = ctx.Tags.Include(t => t.PostTags)
             .ThenInclude(p => p.Post).FirstOrDefault(d => d.TagId == "2");

var posts = tag.PostTags.Select(c => c.Post).ToList();

注意:有时VS没有正确显示智能感知。所以要注意intellisense:D。一种解决方案可能是:关闭VS并启动它的新实例。

例如: intellisense对此.Include(t => t.PostTags)工作正常。但要注意这个.ThenInclude(p => p.Post)。你必须不依赖它而写智能感知。希望微软能够在VS的未来版本中解决这个问题。

结果:

tag的价值:

enter image description here

posts

enter image description here

测试数据:

enter image description here

enter image description here

enter image description here

更新:

它正在工作。请看代码。

var currency = db.Currecies.Include(t => t.RegionCurrencies)
                           .ThenInclude(p => p.Region)   
                           .FirstOrDefault(t => t.UID == Guid.Parse("0f8fad5b-d9cb-469f-a165-70867728950e"));

var regions = currency.RegionCurrencies.Select(c => c.Region).ToList();

结果:

currency的价值:

enter image description here

regions

enter image description here

Git Repo: EfCoreManyToMany