2

并提前感谢您的时间。

我们使用的是 CSLA 3.5.1,尽管最终这个问题可能与 CSLA 没有太大关系。

我的公司在常见建模错误的道路上走了很长一段路,最终不得不面对它。我已经简化了下面的域对象以澄清问题:

我们有 3 个这样定义的类:

类人:BusinessBase

班级学生:人

班主任:人

我们在 ORM 中使用 NHibernate,Student 和 Teacher 类在我们的映射中是 Person 的子类(我们有 Person、Student 和 Teacher 表),使用 PersonID 作为派生键。

正如您可能已经预料到的那样,问题是现在我们有一个学生也可以成为老师的情况。在当前的对象和数据模型下,当我们尝试添加一个已经是教师的学生时,这会导致主键冲突,反之亦然。

问题一:在保存新记录之前,我可以在业务对象上执行任何 CSLA 魔术来防止这种情况吗?

如果不...

在研究这个问题时,我看到了两个解决它的建议,第一个是支持组合而不是继承。据我了解,这意味着 Student 和 Teacher 将各自包含一个 Person 属性。

问题二:为了让它工作,假设学生表和教师表需要一个外键进入 Person 表是否正确?我想我对这个解决方案没有完整的了解,并希望得到一些指导。

第二种解决方案涉及将学生和教师视为特定人所扮演的角色。从我所见,Person 类需要一个 Roles 集合,并且链接表(PersonRoles?)用于将 Student 和 Teacher 表中的记录映射到 Person。

问题三:Role 基类和 PersonRoles 表是什么样的?我相信 Student 和 Teacher 子类只会包含它们适当的属性。它是否正确?

对解决方案有任何意见吗?如果有人能在网上找到一个充实的例子,我很乐意看到它。

谢谢,

将要。

4

3 回答 3

1

问题1:据我所知。这没什么好说的。我没有使用过 CSLA,但我的想法是这是 NHibernate 的事情,必须用 NHibernate 来解决。

问题 2:是的,从概念上讲。一个人有零对一个学生和零对一个教师,但所有学生和教师都需要一个人引用。我为此使用 Fluent NHibernate,因此您必须查找等效的 HBM 语法,但是:

public class PersonMap:ClassMap<Person>
{
    public PersonMap()
    {
        Table("Person");
        Id(x=>Id).Column("PersonID");
        References(x=>x.Student).KeyColumn("StudentID")
            Nullable().Cascade.All();
        References(x=>x.Teacher).KeyColumn("TeacherID")
            Nullable.Cascade.All();
    }
}


public class TeacherMap:ClassMap<Teacher>
{
    public TeacherMap()
    {
        Table("Teacher");
        Id(x=>Id).Column("TeacherID");
        References(x=>x.Person).KeyColumn("PersonID")
            .Not.Nullable().Cascade.None();        
    }
}

public class StudentMap:ClassMap<Student>
{
    public StudentMap()
    {
        Table("Student");
        Id(x=>Id).Column("StudentID");
        References(x=>x.Person).KeyColumn("PersonID")
            .Not.Nullable().Cascade.None();        
    }
}

现在,Person 是这个对象图的顶点;您可以检索 People、Student 或 Teachers,但在保存更改时,始终保存 Person,并且该 Person 的子角色也将被保留。

于 2011-03-28T20:57:41.370 回答
1

只是为了详细说明基思的答案-
q2。值得补充的是,现在您的对象模型(类)看起来像这样:

    public class Student
{
    public IEnumberable<Class> ClassesIAttend {get; set}
    ...
}

public class Teacher
{
    public IEnumberable<Class> ClassesITeach {get; set;}
    ...
}

public class Person : BussinesBase
{
    //either of these can be null
    private Student studentPart;
    private Teacher teacherPart;

    public bool IsTeacher()
    {
        return teacherPart != null;
    }
}   

q3。角色,AFAIK,更像是一种行为(通常是授权)的事情。含义-您通常不使用角色来存储数据。因此,仅当学生和教师之间的唯一区别是允许他们执行的操作时,才建议您使用这种方法。
即使在这种情况下,我也建议不要这样做,因为它不会给你未来的灵活性。

总而言之,我认为组合解决方案是您最好的选择。

于 2011-03-29T12:46:30.797 回答
1

您应该设计模型以支持您的应用程序必须支持的使用场景。

有以下假设:

  • 人员可以是班级中的教师和/或学生。

模型

Person : BusinessBase<Person> 对单一身份建模。

PersonList : BusinessListBase<PersonList, Person> 系统中所有身份的列表。

Student : BusinessBase<Student> 为学生聚合具有其他属性和行为的人员。

StudentList : BusinessListBase<StudentList, Student> 所有学生的名单。

Teacher : BusinessBase<Teacher> 为教师聚合具有附加属性和行为的人员。

TeacherList : BusinessBase<TeacherList, Teacher> 所有教师名单。

Class : BusinessBase<Class> 为单个类建模

ClassTeacher : BusinessBase<ClassTeacher> 模拟一个班级的老师。

ClassTeacherList : BusinessListBase<ClassTeacherList, ClassTeacher> 班级教师名单。

ClassStudent : BusinessBase<ClassStudent> 在班级中为学生建模。

ClassStudentList : BusinessListBase<ClassStudentList, ClassStudent> 一个班级的学生名单。

有了这样的模型,即使在同一个班级,也无法阻止 Person 同时成为学生和教师。

每个类(或此类的 DTO)都可以使用 NHibernate 映射到相关的数据表。例如,在获取 a 时,Student您可能正在从 Student 和 Person 表中获取数据。

于 2011-03-30T11:20:36.937 回答