2016-10-28 4 views
1

Кто-нибудь знает, как запросить БД в EF Core для отношений «многие ко многим», но больше похоже на левое внешнее соединение с одной стороны?Невозможно запросить отношения «многие ко многим»

Позвольте мне объяснить, что я имею в виду.

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 отношений и I хотите получить валютную сущность, даже в таблице RegionCurrency нет записи.

этого (и подобных попыток) закончилась исключением, как это:

Исключение типа «System.ArgumentException» произошло в Microsoft.EntityFrameworkCore.dll, но не был обработан в пользовательском коде

Дополнительная информация : Выражение свойства 'rc => {из RegionCurrency rc в rcs select [pts] .Regions}' недопустимо. Выражение должно представлять доступ к свойствам: 't => t.MyProperty'. Для получения дополнительной информации о включении связанных данных см. http://go.microsoft.com/fwlink/?LinkID=746393.

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

Я не могу найти какой-либо рабочий пример. Но, конечно, я просто слепой.

Спасибо за любую помощь.

ответ

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 должным образом. Поэтому будьте осторожны с intellisense: D. Одним из решений может быть следующее: закрыть VS и запустить новый экземпляр.

Например: IntelliSense работает отлично для этого .Include(t => t.PostTags) .Но остерегаться на этой .ThenInclude(p => p.Post) .Вы должны написать его, не полагаясь на IntelliSense. Надежда Microsoft исправит эту проблему в будущих выпусках VS.

Результат:

значение tag:

enter image description here

значения posts:

enter image description here

Тестовые данные:

enter image description here

enter image description here

enter image description here

Update:

Это working.Please увидеть код.

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

+1

Извините, но это не сработает. Я предполагаю, что Include (t => t.PostTags) вернет IIncludableQueriable <тег, список >, поэтому не будет свойства p.Post для ThenInclude, но только методы List, потому что тип List будет на выходе с первого Включают. – Tomino

+0

Я не вижу никакой проблемы там. Пожалуйста, см. Мое обновление. – Sampath

+0

Чем вы хотите обновить свой ответ. См. Мой обновленный вопрос (изображение). Это скриншот из реального проекта, где отношения определяются так же, как и в примере проекта. – Tomino

Смежные вопросы