代码之家  ›  专栏  ›  技术社区  ›  ScottishTapWater

使用EF防止公开更改收藏内容

  •  0
  • ScottishTapWater  · 技术社区  · 4 年前

    This answer 表示防止对集合内容进行公共访问修改的最佳方法是只公开集合的可枚举项。

    但是,我认为在使用Entity Framework对来自支持数据库的集合进行水合时,这是不可能的,因为这会调用空构造函数并分配属性。

    有办法解决这个问题吗?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Steve Py    4 年前

    不具体。我使用的模式是将设定者标记为 internal 并使用公共变异器方法来处理更新。这并不限制对实体集合(需要 ICollection<T> 至少),但如果它提供了一个标准且易于遵循的路径,那么相信所有开发人员都会使用它。

    收集的模式是:

    public virtual ICollection<Child> Children { get; internal set; } = new List<Child>();
    

    没有什么能阻止代码与Children集合进行交互 .Children.Add(new Child { /* ... */ }); 但是,如果我的上级班级提供:

    public Child AddChild(string Name, DateTime dob /*, ... */)
    {
       // TODO: Validate passed in parameters, look for duplicates, etc... 
       var child = new Child{ /* ... */, Parent = this };
       Children.Add(child);
       return child;
    } 
    

    …然后很容易在子集合之类的东西上进行查找用法,或者注意到提供的Add方法没有被使用,如果其他开发人员偏离了模式,可以向他们提出这个问题。变异器的好处是,它确保提供所需的一切,这样生成的对象就可以被信任为完整有效的。没有 开发人员可以使用mutator方法,但这让他们不用担心不完整的状态,也不用解释为什么他们选择不使用它。试图严格执行一个模式可能很困难,最终可能会使你的代码库变得不灵活,并错过EF等技术可以提供的许多好处。好的模式应该根据其自身的优点来推广,使开发人员的生活更轻松。

    最终,我要避免的关键是不要将实体传递到负责Contoso作用域的代码边界之外。即,如果我处理的是表示层和服务层,其中服务通过EF实体与域交互,那么服务不会将实体传递给表示层。(可能希望最终操纵该领域)相反,可以向表示层提供POCO视图模型或DTO,这些模型具有更严格的约束条件,然后将其传递回服务以处理实体。这样,在实体边界之外可以受到更严格的约束,而不会影响EF功能。(即利用Linq表达式中的导航属性)