根据这篇文章Exposing Private Collection Properties to Entity Framework,我试图让我的模型中的集合属性不被公开。该技术证明了单个级别包含的工作正常,但我无法让它在多个级别上工作。
在我的示例模型中,我有训练师。培训师有培训课程。 TrainingCourses有TrainingClasses。我在培训师中定义了以下内容:
public class ORMappings
{
public const string TrainingCoursesCollectionName = nameof(Trainer._trainingCourses);
public static Expression<Func<Trainer, ICollection<TrainingCourse>>> TrainingCourses
{
get { return t => t._trainingCourses; }
}
}
这样可以正常工作(包括一个深刻的集合),我可以像这样引用它:
return _dbContext.Set<Trainer>()
.Include(Trainer.ORMappings.TrainingCoursesCollectionName);
或
// using System.Data.Entity extension
return _dbContext.Set<Trainer>()
.Include(Trainer.ORMappings.TrainingCourses);
我指的是the documentation on how to include nested collection properties。它表明以下内容应该有效:
要包含一个集合,然后将一个集合包含在一个级别: query.Include(e =&gt; e.Level1Collection.Select(l1 =&gt; l1.Level2Collection))。
但是,我似乎无法找到一种方法来使用.Select()来包含每个TrainingCourse使用上面显示的强类型表达式引用的TrainingClasses(TrainingCourse对其TrainingClasses列表有一个类似的ORMappings类)。我是否尝试在ORMappings类之外(例如在存储库或类似程序中)或在我可以直接访问我的私有_trainingCourses列表的地方这样做并不重要。除了TrainingCourses之外,我还可以使用单独的ORMappings表达式,包括TrainingClasses,如果我可以使用它。我的目标是能够指定集合树中应该填充对象的深度,以便我只根据给定操作的需要加载数据。
有关其他参考,以下是Trainer如何定义其与TrainingCourse的关系:
private List<TrainingCourse> _trainingCourses { get; } = new List<TrainingCourse>();
public IEnumerable<TrainingCourse> TrainingCourses
{
get
{
return _trainingCourses
.Where(tc => tc.IsActive)
.AsEnumerable();
}
}
答案 0 :(得分:0)
internal
和protected
。如果要将域类与基础结构分开,则应创建不同的项目。如果要将域分成几个部分,请使用EntityFramework搜索BoundedContext策略。
回到你的问题,在你目前的情况下,我认为最简单的解决方法是创建一个新的属性:
public static Expression<Func<Trainer, IEnumerable<ICollection<TrainingClass>>>> TrainingCoursesWithClasses
{
get { return t => t._trainingCourses.Select(i => i.TrainingClasses); }
}
未经测试的代码,但如果您当前的代码有效,这也应该有用。
另外,请注意:
public IEnumerable<TrainingCourse> TrainingCourses
{
get
{
return _trainingCourses
.Where(tc => tc.IsActive)
.AsEnumerable();
}
}
这可能会生成IEnumerable的多个枚举。如果您希望每次获得该属性时只获得“IsActive == true”,则应创建DbCommandTreeInterceptor
。
此外,没有理由使集合“私有”并创建一个返回集合的公共表达式;完全没有理由。可以使用以下方式轻松访问该集合:
var traininCoursesLambda = Trainer.TrainingCourses;
var trainingCourses = traininCoursesLambda.Compile().Invoke(trainer);
希望它有所帮助!