Описание
При попытке нетерпеливо .Include()
Многие-ко-многим ICollection
свойств уже вложенного ICollection
я получаю EntityCommandCompilationException
с innerException
: System.NotSupportedException: APPLY joins are not supported.
- Существуют ли (подходящие) обходные пути или это просто не поддерживается EF6 / SQLite?Если не поддерживается, сработает ли миграция на EntityFramework.Core?
- Если некоторые из вас смогут подтвердить, что это ограничение, я бы создал проблему на трекере SQLite
Краткое описание проблемы
// Bare minimum model definitions - see below for a full implementation
public class Mode
{
[Key] public int Id { get; set; }
}
public class Type
{
[Key] public int Id { get; set; }
}
public class Preset
{
[Key] public string PresetId { get; set; }
/* Note: Both Types and Modes are Many-To-Many Entity Relationship configured
* using Join Table/Fluent API */
public ICollection<Type> Types { get; set; } = new List<Type>();
public ICollection<Mode> Modes { get; set; } = new List<Mode>();
}
public class Plugin
{
[Key] public int Id { get; set; }
public ICollection<Preset> Presets { get; set; } = new List<Preset>();
}
public void test ()
{
context.Plugins
.Include("Presets.Modes")
.Include("Presets.Types")
.Load();
}
// EntityCommandCompilationException An error occurred while preparing the command definition. See the inner exception for details.
// innerException System.NotSupportedException: APPLY joins are not supported
Это основной код, который не работает.Ниже приведен полный код и описание реализации моделей.
В отличие от этого, включая один из двух ICollection
навигационных свойств, работает нормально:
context.Plugins
.Include("Presets.Modes")
.Load();
Кроме того, включая более одного ICollection
на одном уровне, работает нормально:
context.Presets
.Include("Modes")
.Include("Types")
.Load();
Дополнительная информация, окружающая среда
- Проблема затрагивает только EntityFramework6 вместе с System.Data.SQLite.EF6 .Насколько я знаю, EntityFramework.SqlServerCompact не затронут.
- Я использую EF6 Code-First, я не пробовал EF6 Model-First или Database-First (и переключаюсь на любой изэто неприменимое решение)
- Проблема возникает только со свойствами навигации коллекции «многие ко многим», и только если я пытаюсь загрузить несколько на одном уровне
- альтернативы, в том числе Select (), которая выдает то же исключение
- Я не пробовал создавать ручные объединения или запросы, так как это привело бы к чрезвычайной потере обслуживания кода в моем проекте
- На данный момент,Я полагаю, что основной причиной является ограничение реализации SQLite EF6 (которая, кажется, не документирована), а не то, что я мог бы легко исправить с помощью кода
- Я нашел только один подобный вопрос StackOverflow относительно нескольких
.Include()
, и (ужасно использовать) средство отслеживания ошибок SQLite, а также списки рассылки, кажется, не упоминаютОсобая проблема - Полный исходный код, включая тестовую базу данных с тестовыми данными, можно найти в моем GitHub EntityFrameworkResearch репозитории .В частности, Определения модели , DbContext и код репро
Код ссылки
public class Mode
{
[Key] public int Id { get; set; }
public ICollection<Plugin> Plugins { get; set; }
public ICollection<Preset> Presets { get; set; }
public string Name { get; set; }
}
public class Type
{
[Key] public int Id { get; set; }
public ICollection<Plugin> Plugins { get; set; } = new List<Plugin>();
public ICollection<Preset> Presets { get; set; } = new List<Preset>();
public string Name { get; set; }
public string SubTypeName { get; set; }
}
public class Plugin
{
[Key] public int Id { get; set; }
public ICollection<Preset> Presets { get; set; } = new List<Preset>();
public ICollection<Type> DefaultTypes { get; set; } = new List<Type>();
public ICollection<Mode> DefaultModes { get; set; } = new List<Mode>();
}
public class Preset
{
[Key] public string PresetId { get; set; } = Guid.NewGuid().ToString();
[ForeignKey("Plugin")] public int PluginId { get; set; }
public Plugin Plugin { get; set; }
public ICollection<Type> Types { get; set; } = new List<Type>();
public ICollection<Mode> Modes { get; set; } = new List<Mode>();
}
public class ApplicationDatabaseContext : DbContext
{
// Constructor and further database initialization omitted for clarity
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Plugin>()
.HasMany(p => p.DefaultModes)
.WithMany(q => q.Plugins)
.Map(mc => mc.MapLeftKey("PluginId").MapRightKey("ModeId").ToTable("PluginModes"));
modelBuilder.Entity<Plugin>()
.HasMany(p => p.DefaultTypes)
.WithMany(q => q.Plugins)
.Map(mc => mc.MapLeftKey("PluginId").MapRightKey("TypeId").ToTable("PluginTypes"));
modelBuilder.Entity<Preset>()
.HasMany(p => p.Types)
.WithMany(q => q.Presets)
.Map(mc =>mc.MapLeftKey("PresetId").MapRightKey("TypeId").ToTable("PresetTypes"));
modelBuilder.Entity<Preset>()
.HasMany(p => p.Modes)
.WithMany(q => q.Presets)
.Map(mc => mc.MapLeftKey("PresetId").MapRightKey("ModeId").ToTable("PresetModes"));
}
public DbSet<Plugin> Plugins { get; set; }
public DbSet<Preset> Presets { get; set; }
public DbSet<Mode> Modes { get; set; }
public DbSet<Type> Types { get; set; }
}