需要领域建模建议 - 希望是常见场景

发布于 2024-10-27 12:52:11 字数 960 浏览 4 评论 0原文

提前感谢您的宝贵时间。

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

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

我们有 3 个类定义如下:

class Person : BusinessBase

class Student : Person

class Teacher : Person

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

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

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

如果不是......

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

问题二:为了使其正常工作,假设 Student 和 Teacher 表需要 Person 表中的外键是否正确?我想我对这个解决方案还没有完全理解,并且需要一些指导。

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

问题三:Role 基类和 PersonRoles 表是什么样的?我相信学生和教师子类只会包含它们适当的属性。这是正确的吗?

对解决方案有什么意见吗?如果有人可以在网上找到一个充实的示例,我很乐意看到它。

谢谢,

威尔。

and thanks in advance for your time.

We are using CSLA 3.5.1, although, ultimately, this problem may not have much to do with CSLA.

My company has gone a long way down the road of a common modeling error and is finally having to face it. I've simplified the domain objects below to clarify the problem:

We have 3 classes defined as such:

class Person : BusinessBase

class Student : Person

class Teacher : Person

We are using NHibernate for our ORM, and the Student and Teacher classes are joined subclasses of Person in our mappings (we have Person, Student, and Teacher tables), using the PersonID as a derived key.

The problem, as you may have anticipated, is now we have a situation where a Student can also be a Teacher. Under the current object and data models, this causes a primary key violation when we try to add a Student that is already a Teacher or vice-versa.

Question One: Is there any CSLA magic I can perform on the business object before saving the new record to prevent this situation?

If not...

In researching this problem, I've seen two suggestions to solve it, The first is to favor composition over inheritance. To my understanding, this means Student and Teacher would each contain a Person property.

Question Two: In order to get this to work, is it correct to assume the Student and Teacher tables would need a foreign key into the Person table? I guess I don't have a complete understanding of this solution, and would like some guidance.

The second solution involves thinking of Student and Teacher as Roles a given person plays. From what I've seen, the Person class would need a Roles collection, and link table (PersonRoles?) is used to map the records in the Student and Teacher tables to the Person.

Question(s) Three: What do the Role base class and the PersonRoles table look like? I believe the Student and Teacher subclasses would just contain their appropriate properties. Is this correct?

Any opinions on a solution? If anyone can find a fleshed-out example on the web, I'd love to see it.

Thanks,

Will.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我很坚强 2024-11-03 12:52:11

问题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 是该对象图的顶点;您可以检索人员、学生或教师,但在保存更改时,请始终保存人员,并且该人员的子角色也将被保留。

Question 1: Not to my knowledge. That's not saying much; I haven't used CSLA, but my thoughts are that this is an NHibernate thing, and has to be solved with NHibernate.

Question 2: Yes, conceptually. A Person has zero to one Students and zero to one Teachers, but all Students and Teachers require a Person reference. I use Fluent NHibernate for this, so you'll have to look up the equivalent HBM syntax, but:

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();        
    }
}

Now, Person is the apex of this object graph; you may retrieve People, Students or Teachers, but when saving changes, always save the Person, and the child roles of that Person will also be persisted.

银河中√捞星星 2024-11-03 12:52:11

只是为了详细说明基思的答案-
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,角色更多的是一种行为(通常是授权)的事情。意思是-您通常不使用角色来存储数据。因此,仅当学生和教师之间的唯一区别是允许他们执行的操作时,这种方法才适合您。
即使在这种情况下,我也会建议不要这样做,因为它不会给你的未来留下太多的灵活性。

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

just to elaborate on Keith's answer-
q2. it's worth adding that now your object model (classes) would look something like so:

    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. roles, AFAIK, is more of a behavioral (usualy authorization) thing. Meaning- you don't usually use roles to store data. so this approach would be advisable for you only if the only differences between Student and Teacher are the actions they're allowed to perform.
Even in that case I would recommend against it, since it doesn't leave you with much flexibility for the future.

All in all, I think the composition solution is your best bet.

静赏你的温柔 2024-11-03 12:52:11

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

假设如下:

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

模型

Person:BusinessBase
塑造单一身份。

PersonList:BusinessListBase
系统中所有身份的列表。

学生:BusinessBase<学生>
为学生聚合具有附加属性和行为的人。

学生列表:BusinessListBase<学生列表,学生>
所有学生的名单。

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

TeacherList:BusinessBase
所有教师的名单。

类:BusinessBase
建模单个类

ClassTeacher : BusinessBase
塑造班级老师的形象。

ClassTeacherList:BusinessListBase
班级教师名单。

ClassStudent:BusinessBase
为班级中的学生建模。

ClassStudentList:BusinessListBase
班级学生名单。

使用这样的模型,即使在同一个班级中,也无法阻止 Person 同时担任学生和教师。

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

You should design the model to support the usage scenarios your application must support.

With the following assumptions:

  • Person can be Teacher and/or Student in a Class.

Model

Person : BusinessBase<Person>
Models a single identity.

PersonList : BusinessListBase<PersonList, Person>
List of all identities in system.

Student : BusinessBase<Student>
Aggregates a Person with additional properties and behaviour for student.

StudentList : BusinessListBase<StudentList, Student>
List of all students.

Teacher : BusinessBase<Teacher>
Aggregates a Person with additional properties and behaviour for teacher.

TeacherList : BusinessBase<TeacherList, Teacher>
List of all teachers.

Class : BusinessBase<Class>
Models a single class

ClassTeacher : BusinessBase<ClassTeacher>
Models a teacher of a class.

ClassTeacherList : BusinessListBase<ClassTeacherList, ClassTeacher>
List of a class' teachers.

ClassStudent : BusinessBase<ClassStudent>
Models a student in a class.

ClassStudentList : BusinessListBase<ClassStudentList, ClassStudent>
List of a class' students.

With such a model there's no stopping Person from simultaneously being Student and Teacher even in the same class.

Each class (or DTO for such) can be mapped to the relevant data tables using NHibernate. For example, when fetching a Student you could be fetching data from the Student and Person tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文