2013-10-31 178 views
1

我有一个关于大学管理的.net解决方案(使用实体框架,使用CodeFirst方法)。该项目的结构是这样的:实体框架:具有关系和更多关系的对象设计

  • 数据访问(的DbContext和通用库)
  • 实体(代码第一类)
  • 服务(服务类)
  • 网站(一个MVC项目,对于解释不重要)

为了使问题更容易,我只从我的域名谈(上实体层)大概有两班:

  • 学生

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

Course.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); 
    } 
} 

正如你所看到的,类有增加学生课程的属性。 情况是,验证正在增长,现在非常复杂,它需要对数据库进行一些查询等等。所以课程有很多责任!

所以我认为,我需要一个服务来处理“添加”,并进行所有验证,并从课程类别远离这种责任。问题是,因为学生系列私人成员课程,我不能添加学生从服务类的课程。

另一种方式,我认为要解决的问题,是增加了相关实体(学生)的情况下(从服务),但它会打破我的(因为我将不得不做出的DbContext上市)。如果我直接使用Service类中的DbContext,则存储库没有意义,不是吗?

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

谢谢!

回答

1

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

我是DDD或Domain-Driven Design的忠实粉丝。您可能想要问的一些问题包括:

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

还有其他的,但绝对要全面看待你的问题和你的对象的设计方式。添加学生课程与添加课程给该学生一样吗?

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

在任何情况下,我都会推荐Julie Lerman关于面向数据的EF人员的DDD系列:http://msdn.microsoft.com/en-us/magazine/dn342868.aspx

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

+0

我会回答你的问题: 1)不,它不一定是一种方法。是的,我想要的是“注册”学生的概念。但我不知道如何设计类来进行验证并正确保存数据。我清楚了吗?你如何做到“登记”(不详细,但在更高的水平)? 2)是否有学生存在课程概念之外。确切地说,他们可以采取多种课程。但为什么它不应该因为这个私人?我不希望客户端应用程序(程序员)能够向学生添加课程或课程的学生,而无需进行正确的验证。 –

0

我不同意实体中的方法如AddStudent(...)。让实体成为简单的数据传输对象 - 即POCO--进入和离开EntityFramework。我更愿意让我的业务逻辑处理这些事情。

您可以将IdCourseStudents设置为私人。我见过其他人也使用protected ......但是为什么?有一个实体的后代吗?

由朱莉·勒曼的喜好推荐ICollection<T>性质的一种解决方案是:

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封装)将跟踪变化Course和添加新学生或Student的关系到Course的。至于使用私有或受保护的setter,我想限制开发人员访问更改ID/Keys或重新分配整个集合引用。

+0

关于“AddStudent”方法,我同意你的看法,这就是为什么我想从“课程”类中拿出这种方法的原因! IdCourse和学生可以是私人的,我不能回答你的问题,因为我没有理由让它受到保护,但这不是我来这里的主要原因,所以也许我们可以跳过这个话题:P(但如果您有任何意见,我想知道!) 关于朱莉勒曼的建议,这很好,我会用它,但它不能帮助解决我的问题:我如何添加学生从课程(知道学生收集制定者是私人的)? –

+0

感谢您的帮助,但有一个问题。如果您可以从服务中添加这样的学生,则可以通过应用程序以相同方式添加学生,并且我希望避免在未进行验证的情况下将学生添加到课程中! 我该如何避免这种情况? –

+0

不要在应用程序层使用POCO。在存储库/业务层和表示层之间使用DTO或DataTransferObjects。此外,提供某种验证的添加过程,以确保:适当的凭据,正确的方法论/方法序列等。这有帮助吗? – IAbstract