繁体   English   中英

实体框架-包含具有不同子类的多个级别的属性

[英]Entity Framework - Include Multiple Levels of Properties with different subclasses

我正在努力解决实体框架中的问题-包括多个级别的属性

给定这些类:

class Survey {
    public virtual List<QuestionBase> Questions {get;set;}
    ...
}

class QuestionType1 : QuestionBase {
    public List<Answers> Answers {get;set;}
    ...
}
class QuestionType2 : QuestionBase {
    ...
}

Iam试图获取用于深度克隆的实例,但无法使用以下方法获得答案:

Survey originalEntity = DBSet
            .Include(s => s.Questions)
            .Include(s => s.Questions.OfType<QuestionType1>().Select(q => q.Answers))
            .AsNoTracking()
            .Single( e => e.Id == sourceId );

使用此方法,我会收到错误消息“包含路径表达式必须引用在类型上定义的导航属性。 使用虚线路径作为参考导航属性,使用“选择”运算符作为集合导航属性。 参数名称:路径'

好了,所以这花了我比我想象的更长的时间,但是我想出了一个解决方案。 但是,请注意,这不是“ full-LINQ”解决方案,您需要一个DB-Context实例。 我希望这可以满足您的需求。 解决方案的关键部分是为QuestionType1每个实例显式加载Answers集合。

Survey survey;
int sourceId = 1;

using (var context = new YourDbContext())
{
  survey = context.Surveys.Include(s => s.Questions).Single(s => s.Id == sourceId);
  var questions = survey.Questions.OfType<QuestionType1>();
  foreach (var question in questions)
  {
    context.Entry(question).Collection(q => q.Answers).Load();
  }
}

/* just for testing to check if Questions and Answers are correctly loaded... */
Console.WriteLine(survey);
foreach (var questionBase in survey.Questions)
{
  Console.WriteLine("Question id " + questionBase.Id);
  var questionType1 = questionBase as QuestionType1;
  if (questionType1 != null)
  {
    foreach (var answer in questionType1.Answers)
    {
      Console.WriteLine("Answer " + answer.Id);
    }
  }
}

备注:

对于一个非常罕见的用例,这是一个非常罕见的解决方案。 如果您确实确实需要这种行为,或者可以提出更通用,更简单的解决方案,则可能需要重新考虑。

为了帮助其他有相同问题的人,我将在这里发布我的解决方案:

Survey cloneSurvey = Context.Surveys
            .Include( s => s.Questions )
            .AsNoTracking()
            .FirstOrDefault( e => e.Id == sourceId );
        Context.Surveys.Add( cloneSurvey );

        IEnumerable<QuestionType1> questions = cloneSurvey.Questions.OfType<QuestionType1>();
        foreach( QuestionType1question in questions )
        {
            IEnumerable<Answer> answers = Context.Answers.AsNoTracking().Where( a => a.Question.Id == question.Id );
            foreach( Answer answer in answers )
            {
                Context.Set<Answer>().Add( answer );
                question.Answers.Add( answer );

            }
        }
        Context.SaveChanges();

尝试了很多解决方案,最后我最终遍历了问题和答案,将每个答案添加到Context.Set

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM