我正在努力解决Entity Framework - Include Multiple Levels of Properties
中的问题鉴于这些课程:
class Survey {
public virtual List<QuestionBase> Questions {get;set;}
...
}
class QuestionType1 : QuestionBase {
public List<Answers> Answers {get;set;}
...
}
class QuestionType2 : QuestionBase {
...
}
Iam尝试获取深度克隆的实例,并且无法使用以下内容获取Answers:
Survey originalEntity = DBSet
.Include(s => s.Questions)
.Include(s => s.Questions.OfType<QuestionType1>().Select(q => q.Answers))
.AsNoTracking()
.Single( e => e.Id == sourceId );
使用这个我得到错误'包含路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性。 参数名称:路径'
答案 0 :(得分:0)
好吧,所以这比我想象的要长,但我想出了一个解决方案。但请注意,这不是“完整LINQ”解决方案,您需要一个DB-Context实例。我希望这对你的需求没问题。解决方案的关键部分是为Answers
的每个实例显式加载QuestionType1
集合。
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);
}
}
}
对于一个非常罕见的用例,这是一个非常罕见的解决方案。如果您确实需要这种行为,或者您可以提出更常见,更简单的解决方案,您可能需要重新考虑。
答案 1 :(得分:0)
为了帮助其他人解决同样的问题,我将在此处发布我的解决方案:
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