3

First of all I am making it clear that, I am not using any OR Mapper framework to solve this problem, coz I need to understand the model from the ground up.

OK. Let's see the table designs:

Course - table

------------------
 ID | CourseName
------------------
 1  |  C++
 2  |  Java
------------------

Teacher - table

-----------------------
 ID |   TeacherName
-----------------------
 1  |   Professor X
 2  |   Professor Y  
-----------------------

CourseTeacher - table

---------------------------------------------
 ID | CourseID | TeacherID | ClassTime
---------------------------------------------
 1  |   1      |     1     | Monday    10:55
 2  |   1      |     2     | Thursday  10:55
 3  |   2      |     1     | Tuesday   11:45
 4  |   2      |     2     | Wednesday 11:45
---------------------------------------------

How should I design my classes in C#?

There can be another problem like is:

User - table

------------------
 ID | UserName
------------------
 1  |  a
 2  |  b
------------------

Role - table

-----------------------
 ID |   RoleName
-----------------------
 1  |   c
 2  |   d
-----------------------

UserRole - table

---------------------------------------------
 ID | UserID | RoleID | Remarks
---------------------------------------------
 1  |   1      |     1     | xy
 2  |   1      |     2     | yz
 3  |   2      |     1     | zx
 4  |   2      |     2     | xx
---------------------------------------------
user366312
  • 16,949
  • 65
  • 235
  • 452

4 Answers4

4

In general, when you have a many-to-many relationship in your domain model, the access patterns in your code will either be from one side of the M2M or from the other...

For e.g. If you have a structure containing people, each of whom has made a number of purchases at your retail outlets, you might as a rule want to access those transactions thrpugh a person, not through the product. in other words, you might more often want to know what products a specific person purchased, not what people purchased a specific product. So in this example you would simply have each person class contain a property which is a collection of products. There would be no need to access the person class through the Product class.

Another e.g. If you have a a structure containing people, each of whom subscribes to a number of magazines.

Now if you are the publisher, you might as a rule want to access those transactions through the magazine, not through the person. in other words, you would much more often want to know what people subscribe to a specific magazine, not what magazines a specific person subscribes to. So in this example you would put a Subscribers collection property in the Magazine class.

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
3

I thinkt that you actually have a hidden third concept there: a ClassSession, or something like that. Each ClassSession would have a Teacher, a Course and a DateTime.

public class ClassSession
{
    public Teacher Teacher { get; set; }

    public Course Course { get; set; }

    public DateTime Time { get; set; }
}
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • This is the right idea, in my opinion. It's called "reification". – duffymo Dec 28 '10 at 18:00
  • @duffymo, @Mark Seemann: while I think this answer has value for the reason pointed out by @duffymo - brings up nice point of clarifiying the concepts which is definitely good - to know more about the problem. But I think it actually does not really help the @JMSA much as he would like to model this into a class and the above purposed class actually most likely has no value in real life application - it can most be a search method in my opionion FindClassSession(Teacher,Course,Time) but definitely not a class. I would say this is exactly what should not be a class in this case. Just my opinion – user44298 Dec 28 '10 at 23:05
  • @duffymo, @Mark cont' from above: So the @JMSA would have to write an exctra class besides the Teacher & Course classes which he has to maintain and really would have no use for it. So I think it ends up like this: more code to mainain (which may actually not be usefull) because of which @JMSA is prone to make more errors (simply because there is more code to worry about now. So overall I think the post has value for crystallizing the idea of classroom session but not beyond that as the purposed class does not seem to have an adequate real life application. – user44298 Dec 28 '10 at 23:10
  • @duffymo, @Mark cont' from above Of course I maybe wrong and would love to hear more from you guys of how you would actually use this third class - ClassSession. I am open for your comments & like to learn new stuff so I apologize if I missed something in advance. – user44298 Dec 28 '10 at 23:11
  • @ivo s: "above purposed class actually most likely has no value in real life application" - sorry, I think you're wrong. All that stuff you typed? I couldn't disagree more. You've missed everything, in my opinion. – duffymo Dec 28 '10 at 23:22
  • @duffymo : thanks for downvoting my answer first of all, secondly I would like you to elaborate more not just say "I couldn't disagree more. You've missed everything, in my opinion" - as you can see I explain my reasoning I don't just say "It's wrong". So please be kind rewind & explain your opinion & also please comment on my answer why it's wrong too if you don't mind. – user44298 Dec 28 '10 at 23:35
  • @duffymo I'm most interested in how the above class would be used. For example @Viktor Jevdokimov provides a use for it and as you can see it's nothing but update. Why can't you do this directly from the Teacher or Course class ? Why do I need to write an extra class to update a mapping for a teacher to course ? I think you can do it from either or. – user44298 Dec 28 '10 at 23:37
  • Your "reasoning" is not much of a step above "you're wrong". Simply asserting that writing one more class was too much of a maintenance burden and would not be used isn't any improvement. I deliberately used the word "reification" because it's one of the core object-oriented design concepts from Jim Rumbaugh's "OMT Insights" - see 'Let There Be Objects' from Nov 1992. The word means to take an abstract concept and regard it as a concrete thing. The approach that you take is certainly defensible. I happen to think that the design would benefit from another concept. – duffymo Dec 29 '10 at 00:24
  • @duffymo: thanks for responding. Sorry you didn't understand what I was saying, here is clarification: I do say that there is no need for the extra class from practical point of view as there is no extra properties to the relationship between Teacher & Course to justify the creation of the mapping class. I know what you are thinking how about the ClassTime of the session ? If take a closer look you will see that ClassTime is part of the mapping PK. CourseID | TeacherID | ClassTime can be used as PK - hence there is no extra properties to the relations therefore no need for extra class. Cont. – user44298 Dec 29 '10 at 01:05
  • Take a look at this thread http://stackoverflow.com/questions/1103693/c-how-to-model-a-many-to-many-relationship-in-code. So in conclusion I can say that yes you can write this model with the ClassSession but there is no need in this particular case since the date/time of the sessions is actually part of the PK - it's basically a part of the mapping, it's not an extra property. But you can still write a CLassSession class no problem, you can even write 2 such classes but it hs no benefit I believe. Not to mention that introduces an additional concept "Class Session" which the dev must learn. – user44298 Dec 29 '10 at 01:10
  • Lastly: "Simply asserting that writing one more class was too much of a maintenance burden and would not be used isn't any improvement" this isn't at all what I'm trying to put up front, I just point out the obvious - more code more work, it's a side effect. What I do argue is that you don't need an extra class to hold a mapping between a teacher & course. Aslo another big problem that I see here is that I cannot see the practical use of it. You rarely search or display UI screens for "class seesion" rather you display the schedule of a teacher or teachers for course, think about it – user44298 Dec 29 '10 at 01:15
  • it's likely to AddCourse() to a teacher with a DateTime - it's more simple for a developer to pickup this approach then having to understand where to add a course & time slot for a teacher which would be located in the ClassSession class?? I'd be disappointed if I enter a new work place and things are not straight forward Teacher.AddCourse() but it's new ClassSession (Teacher,Course,Datetime). Which one you find easier to understand ? So I am after: 1) Unnecessary complexity without theoretical or practical need 2) No extra properties to justify the mapping class. Otherwise it can be done np. – user44298 Dec 29 '10 at 01:20
  • I understood you completely. There's no misunderstanding. Yours is just a poor, unpersuasive argument. It's my opinion that the design is improved by adding this class. It's clearer, because the things that should be related are encapsulated into a single class. You can embed appropriate logic into that class, where it makes sense. I disagree with your assessment that it's theoretically and practically unnecessary. It's a matter of better encapsulation for me. Once again, I'm unpersuaded by your logic. – duffymo Dec 29 '10 at 01:22
1

My sample:

interface ICourse
{
    string Name { get; set; }
}

interface ITeacher
{
    string Name { get; set; }
}

interface IClassSession
{
    ICourse Course { get; set; }
    ITeacher Teacher { get; set; }
    DateTime Scheduled { get; set; }
}

interface ITransactionalEntity
{
    int ID { get; set; }
}

//sample class implementation
class Teacher : ITeacher, ITransactionalEntity
{
    private int _ID;
    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }
    //implement interfaces
    public void Save(SqlTransaction tran)
    {
        if (this.ID > 0)
            //insert
        else
            //update
    }
}

class ClassSession : IClassSession, ITransactionalEntity
{
    //implement interfaces
    public void Save(SqlTransaction tran)
    {
        this.Course.Save(tran);
        this.Teacher.Save(tran);
        if (this.ID > 0)
            //insert
        else
            //update
    }
}

...
List<IClassSession> list = new List<IClassSession>();
ClassSession cs = new ClassSession();
cs.Course = new Course(courseID);
cs.Teacher = new Teacher(teacherID);
classlist.Add(cs);
SqlTransaction tran;
...
foreach(IClassSession classsession in list)
    classsession.Save(tran);
...

and you can do whatever you want, Linq it, etc. Use your imagination. Not everything is written here, just as an idea.

Viktor Jevdokimov
  • 1,054
  • 6
  • 13
  • Should "if (this.ID > 0)" not be for an update query or else the ID is assigned from database auto-increment on record insert? – J Pollack May 21 '12 at 07:14
0

If you are already comfortable with parent-child relationships then I would suggest that you try to model them as two seperate parent-child relationships. For example have one screen that edits teachers and allows them to add existing courses. On the flip side you can have a course screen that allows them to add existing treachers. Following this advice should make your work easier. From a class design, you would model it the same way. The Course class would have a method to add teachers to the internal list of teachers. The Teacher class would also have a method to add Courses to the internal list of courses. The physical structure of the classes really depends on how you plan to persist the objects. File based persistence, xml serialization and database persistence can have different internal object structures. There are also class differences if you are modeling from an entity level or from a business layer level. In any case, hopefully I have given you enough ideas to run with it.

k rey
  • 611
  • 4
  • 11