5

EDIT: the great early responses made me realize that my question vis a vis tradeoffs would be more useful incorporating @Leo's variation.

I am developing a data model in Code-First EF and feel inexpert on what probably is pretty fundamental.

Given classes Team and Player, where a Team has N Players, the data model can be designed

1) either with the Players as member children objects:

class Team
{
    int Id;
    ICollection<Player> Players;
}

or 2) (REJECTED AS HAVING NO REAL BENEFIT) we can just pass around reference ID's to the players

class Team
{
    int Id;
    ICollection<int> PlayerIds;
}

or 3) implemented with foreign key ID's for model independence

class Team
{
    int Id;
}

class Player
{
    int Id;
    int TeamId;
}

I can see some clear benefits to the 3rd approach, as indicated below by @Leo. So perhaps my question would best be phrased, at this point, as "in what scenarios might one prefer to go with variation 1"?

Alex Edelstein
  • 518
  • 5
  • 19
  • 1
    Are you asking from a DB point of view or a code point of view? I don't know why I'd want to have a collection of IDs so that I can look up associated objects because that's quickly trending towards being a reimplementation of a database. – 48klocs Feb 21 '14 at 02:43
  • Probably not a huge deal but you'll waste memory storing all of the value types plus all of the reference types separately to which those IDs refer. Additionally, your C# code will be much less readable and more bloated because of additional need to fetch the actual Player from some separate list of players somewhere by the id in the team class. It's counter to the idea of oop. – Dmitriy Khaykin Feb 21 '14 at 02:47

4 Answers4

3

Well, I guess you're right, you won't find many resources that outline how you should design you data layer and/or models. Actually, the resources you will find will most-likely depict different ways to do it and perhaps suggest what you should (or should not) do. However, I have found the subject to be extremely subjective and you should never isolate it from the context, what I mean is, only you should know which approach will best suit your circumstances because you are the one who has the best knowledge of your system's intrinsics. Both approaches look fine to me, what you should ALWAYS do is strive to keep loose coupling between sub-systems. Basically, this mapping...

class Team
{
    int Id;
    ICollection<Player> Players;
}

is making Teams dependant on Players, which is fine IF (and only if) it's a requirement that should never change. Furthermore, if Players will always belong to one and only one team then you can take another approach by keeipng your Team model/entity dependency free...

class Team
{
    int Id;
    string TeamName;
}

class Player
{
    int Id;
    int TeamId;
}

Database queries should not be a concern here, your presentation and model layer should try to abstract away from relations, if you can't...say, you need to display/present a team and its players then you will most-likely need 2 database queries(if you don't want to use joins and sanitize the duplicated fields...teams, in this case) and I don't see anything wrong with making 2 separate database queries.

Edit

I guess approach 1 makes coupling even tighter and you should always avoid it, imagine if by any chance you need to chance the name of the Player class, you'd have to make a lot of changes throughout your system. Furthermore, if you are exposing an API it might be even worse for your clients. But, as I said it all depends on the core requirements of your system...if these is a core (hard to change) requirement then you shouldn't worry about it.

"in what scenarios might one prefer to go with variation 1"?

Again, this all about requirements, if your requirements dictate that there is a relationship between Teams and Players then all approaches are fine as long as you can establish a relationship between the two entities.

Community
  • 1
  • 1
Leo
  • 14,625
  • 2
  • 37
  • 55
  • You know, looking at your answer, I realize that your 2nd example, where Team is independent of the Player class, is what I really was trying to express in my own 2nd example. My question would have been better phrased as "What factors make you lean towards model independence via the use of foreign key id's, and what factors would make you lean towards tight coupling of two classes" – Alex Edelstein Feb 21 '14 at 15:54
  • Foreign keys express a relationship and relationships express a dependency where a child is dependent of its parents but the parents are NOT dependent of its children. If you got as far as determining that there is a relationship is because the requirements dictate so. The next thing you need determine how these parties relate to each. The nature of the relationship will dictate when loose coupling is necessary and when it is not. I hope you're getting the idea, coupling is sometimes necessary when establishing a relationship – Leo Feb 22 '14 at 03:42
  • @Leo Having Id of one class in another is same as association? or is it only when the type itself is using as a property in other class? –  Feb 02 '17 at 07:11
2

In my opinion the a answer is: neither.

In Entity Framework you can choose between two types of associations

  • Independent associations, in which you've only got a reference to another object. An example of this is

    class Player
    {
        int Id;
        Team Team;
    }
    
  • Foreign key associations, in which you have a reference and a primitive foreign key value:

    class Player
    {
        int Id;
        [ForeignKey("Team")]
        int TeamId;
        Team Team;
    }
    

Your alternative 2) is not an option because you can't store a list of integers in a database field. Besides, what would you need the Ids for? They're meaningless without the Players.

People coming from a DDD background alway frown upon foreign key associations, because the domain model shouldn't have any notion of store implementations. Still, it is the recommended approach when you work with EF. Here's why:

When you want to store a new player you can either set the Team or the TeamId property. Now if you happen to have the Team around this doesn't matter. However, in many case you'll only have the TeamId (e.g. because it is chosen from a dropdown list). With independent associations you must first make a database roundtrip to fetch the Team and then set the property. Just setting the Id is simpler and performs better.

If you only store TeamId in fact you don't have an association, so this can't be listed as a third alternative for associations. And it's not a viable option. You'll always have to join some way or another to get the associated Team. But what if you want to store a new Team and a new Player in one run? You'll have to store the Team first, get its allocated Id, set the Player's TeamId and store the Player, all wrapped in a TransactionScope. With FK associations you just create the objects, set player.Team = team and EF figures out in which order to insert the objects and sets the FK value for you.

So what I'm trying to say is, DDD principles like loose coupling, separation of concerns at best play a role in the background when it comes to optimizing a class model that serves as a conceptual model for Entity Framework. This class model is not a domain model, it's a data layer first and foremost.

Community
  • 1
  • 1
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
1

I think the trade-off for the minor decrease in coupling is an increase in complexity. In fact I suspect you maintain or increase the amount of coupling in the application as a whole because you're simply shifting the responsibility for obtaining and operating on those objects to a intermediate class - or worse, you start incorporating your data access logic into your models.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
0

Unless Id is relevant in your conceptual model, I would not include it in the model. It seems like it's a detail of the database implementation, and not a true part of the model.

A team has players. It does not have player ids.

You should also consider whether the team Id is even relevant to your model. If you were simulating an (American) football game, then it might matter which number is on the player's jersey. But you would not display the player's employee id.

John Saunders
  • 160,644
  • 26
  • 247
  • 397