2017-01-15 2 views
1

Я с трудом Извлечение данных из производных классовC#, EF, Multi-Level Наследование, данные не Load

В моем примере, я хотел бы вывести данные таким образом, что CoatRecipe имеет CoastSteps, а ScrubRecipes - ScrubSteps.

Все этапы имеют коллекции выходов.

В этом примере данные сохраняются, я могу получить Рецепты, этапы, но выходы не будут восстановлены. Что мне не хватает?

Я должен добавить. В этом примере. Recipe1.Steps не имеет OutputList. OutputList - это то, что я хотел бы получить.

Я использую EntityFramework 6.1

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Data.Entity; 
using System.Data.Entity.Migrations; 
using System.Linq; 

namespace TestApp 
{ 
    internal class Program 
    { 
     public static void Main(string[] p) 
     { 
      DeleteData(); 
      CreateRecipes(); 
      using (var db = new DbModel()) 
      { 
       var recipe1 = (from x in db.recipeDS.OfType<ScrubRecipe>() 
            .Include(x => x.steps) 
           select x).FirstOrDefault(); 

       //var recipe2 = (from x in db.recipeDS.OfType<ScrubRecipe>() 
       //     .Include(x => x.steps.OfType<ScrubStep>().Select(y => y.outputList)) 
       //    select x).FirstOrDefault(); 
      } 
     } 

     private static void DeleteData() 
     { 
      using (var db = new DbModel()) 
      { 
       db.Database.ExecuteSqlCommand("DELETE FROM [StepOutputs]"); 
       db.Database.ExecuteSqlCommand("DELETE FROM [RecipeSteps]"); 
       db.Database.ExecuteSqlCommand("DELETE FROM [Recipes]"); 
      } 
     } 

     private static void CreateRecipes() 
     { 
      // Output to be saved. 
      var stepOutput = new StepOutput(); 

      // Create a Recipe 
      var scrubRecipe = new ScrubRecipe 
      { steps = { new ScrubStep { outputList = { stepOutput } } } }; 

      // Create a Recipe 
      var coatRecipe = new CoatRecipe 
      { steps = { new CoatStep { outputList = { stepOutput } } } }; 

      // Save the Recipes 
      using (var db = new DbModel()) 
      { 
       db.scrubRecipeDS.AddOrUpdate(scrubRecipe); 
       db.coatRecipeDS.AddOrUpdate(coatRecipe); 
       db.SaveChanges(); 
      } 
     } 
    } 

    public abstract class Recipe 
    { 
     [Key] 
     public int ID { get; set; } 

     public List<RecipeStep> steps { get; set; } = new List<RecipeStep>(); 
    } 

    public class CoatRecipe : Recipe { } 

    public class ScrubRecipe : Recipe { } 

    public abstract class RecipeStep 
    { 
     [Key] 
     public int ID { get; set; } 

     public virtual Recipe recipe { get; set; } 
    } 

    public class CoatStep : RecipeStep 
    { 
     public List<StepOutput> outputList { get; set; } = new List<StepOutput>(); 
    } 

    public class StepOutput 
    { 
     [Key] 
     public int ID { get; set; } 

     public virtual RecipeStep recipeStep { get; set; } 
    } 

    public class ScrubStep : CoatStep 
    { 
     public int value { get; set; } 
    } 

    public class DbModel : DbContext 
    { 
     public DbModel() 
      : base("name=DbModelConn") 
     { 
      Database.SetInitializer(new CreateDatabaseIfNotExists<DbModel>()); 
     } 

     public virtual DbSet<Recipe> recipeDS { get; set; } 
     public DbSet<RecipeStep> recipeStepDS { get; set; } 
     public DbSet<StepOutput> stepOutputDS { get; set; } 

     public virtual DbSet<ScrubRecipe> scrubRecipeDS { get; set; } 
     public virtual DbSet<ScrubStep> scrubRecipeStepDS { get; set; } 
     public virtual DbSet<CoatRecipe> coatRecipeDS { get; set; } 
     public virtual DbSet<CoatStep> coatRecipeStepsDS { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<ScrubStep>() 
       .HasMany(x => x.outputList) 
       .WithRequired(x => (ScrubStep)x.recipeStep); 



     } 
    } 
} 
+0

что вы не можете его получить? результат равен нулю? – esiprogrammer

+0

Коллекция Outputs не будет заполняться. Рецепты и шаги. – MIJ1974

+0

Если вы разместите перерыв на рецепте, вы увидите, что рецепт был загружен, а также шаг. Я не мог понять способ включения выходов, поскольку сборка шагов является базовым классом. – MIJ1974

ответ

1

При использовании родительского класса RecipeStep, который не содержит коллекцию, что вам нужно, вы должны будете использовать explicit loading загрузить коллекцию. Вам также нужно будет отнести каждый RecipeStep к дочернему классу, который содержит коллекцию.

foreach (var coatStep in recipe1.steps.OfType<CoatStep>()) 
{ 
    db.Entry(coatStep).Collection(x => x.outputList).Load(); 
} 

Выполнение одного из этих исполнений не будет лучшим, поскольку оно вызывает запрос базы данных с каждой итерацией. Однако, это действительно не должно быть слишком плохо, если у вас нет необычного количества сущностей.

+0

'steps' не имеет свойства' outputlist'. – esiprogrammer

+0

, он не позволит мне включать outputList, поскольку эта процедура относится к базовому типу, а не к производному классу, который мне нужен. – MIJ1974

+0

Это отлично работало с CoatStep, но не с ScrubStep. Я считаю, что я сталкиваюсь с ScrubStep - это другая проблема. Больше проблем с дизайном. Я решил это, создав промежуточный класс, который содержит общие выходы. Спасибо @Matt Rowland, что вы вылечили мой глаз от подергивания, как сумасшедший. – MIJ1974