1

我有一个关于大学管理的 .net 解决方案(使用实体框架,使用 CodeFirst 方法)。项目的架构是这样的:

  • DataAccess(DbContext 和通用存储库)
  • 实体(代码第一类)
  • 服务(服务类)
  • Web(一个MVC项目,解释不重要)

为了使问题更容易,我将只讨论我域中的两个类(在实体层上):

  • 课程
  • 学生

课程可以有很多学生。解决方案的目标是将学生添加到课程中(中间有一些验证)。

课程.cs

public class Course
{
    [Key]
    public int IdCourse { get; protected set; }

    public string Name { get; set; }

    public virtual ICollection<Student> Students { get; protected set; }

    public void AddStudent(Student student)
    {
        // Some Validation
        Students.Add(student);
    }
}

如您所见,该类具有将学生添加到课程的属性。情况是验证越来越多,现在非常复杂,需要对数据库进行一些查询等等......所以课程有很多责任!

所以我想,我需要一项服务来处理“添加”并进行所有验证,并将这种责任从课程课程中拿走。问题是,由于Student CollectionCourse的私人成员,我无法将学生添加到 Service 类的课程中。

我认为解决问题的另一种方法是将相关实体(学生)添加到上下文(来自服务),但这会破坏我的存储库(因为我必须公开DbContext)。如果我直接使用 Service 类中的 DbContext,那么存储库就没有意义了,不是吗?

那么,我应该如何设计呢?或者我应该怎么做才能解决这个问题?任何建议也会很受欢迎!

谢谢!

4

2 回答 2

1

这并不能直接回答您的问题,尤其是与代码优先 EF 相关的所有问题(不是我的专业领域)。但看起来你在这里有一个设计问题。

我是 DDD 或领域驱动设计的忠实粉丝。您可能想问的一些问题包括:

  • “AddStudents”真的应该是一种方法吗?一个对象应该有一个行为,而“添加学生”是一个数据持久性概念,而不是域/实体概念。也许行为会是“注册”?注册可能有自己的逻辑,因此有对象来封装该逻辑。
  • 其次,学生是否存在于他们正在学习的课程的概念之外?例如,他们可以参加多门课程吗?那么这里的集合可能不应该是私有的......应该有一个名为 StudentEnrollment 的新对象吗?

还有其他的,但一定要全面审视你的问题和你的对象的设计方式。添加学生的课程与将课程添加到该学生的课程相同吗?

也许您的服务可以进行验证并将学生添加到课程中,或者将课程添加到学生中(或两者都添加)并将它们保存在自己的存储库中。

无论如何,我会向面向数据的 EF 人员推荐 Julie Lerman 的 DDD 系列:http: //msdn.microsoft.com/en-us/magazine/dn342868.aspx

无论如何,我建议不要公开您的 DbContext!

于 2013-10-31T19:55:50.163 回答
0

我不同意AddStudent(...)实体中的方法。让实体成为进出 EntityFramework 的简单数据传输对象(即 POCO)。我更喜欢让我的业务逻辑来处理这些事情。

您可以将IdCourseand Studentssetter 设置为私有。我也看到其他人也使用protected过……但是为什么呢?有实体的后代吗?

ICollection<T>Julie Lerman 等人推荐的一种房产解决方案是:

private ICollection<Student> _students;  

public virtual ICollection<Student> Students { 
   get; { _students ?? (_students = new Collection<Student>()); }
   private set { _students = value; }
}  

更新来自评论

如果您使用存储库或业务层来查询课程,您可以使用如下方法:

   // this is how I would approach a business layer method
   void AddStudentToCourse(string CourseName, Student NewStudent) {
       // may employ a using block for repository
       // also validate student
       using (var repo = new CourseRepository()) {
          var course = repo.GetCourse(CourseName);
          course.Students.Add(NewStudent);

          repo.Save();
       }
   }

有几种不同的方法可以实现这一点,这个示例远未完成,但应该为您提供一个基本概念。

底层DbContext(由 继承或封装)将跟踪对新学生的CourseRepository更改和添加或与的关系。CourseStudentCourse

至于私有或受保护的设置器的使用,我想限制开发人员访问更改 ID/键或重新分配整个集合引用。

于 2013-10-31T19:59:01.043 回答