views:

194

answers:

4

I'm writing a homework for my RDBMS class, I need to perform CRUD operations on quite simple domain, which is cyber sport championship.
Students are required to use ADO.NET. My question is how can I solve bidirectional relationship, for example 1:m (every championship has many matches, but every match belongs to only one exact championship)? It seems to me that there must be some technique for that.
And the most interesting part for me is - how does ORM like EF or NHibernate solve this situation?

+1  A: 

Have a look at Davy Brions Blog about building your own Data Access Layer. He talks about all those sort of challenges.

Nathan Fisher
A: 

For something like many-to-many with Hibernate, you define the relationship. Here's an example (reference is here:

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true" table="PersonAddress">
        <key column="addressId"/>
        <many-to-many column="personId"
            class="Person"/>
    </set>
</class>

From the database side itself, for many-to-many relationship you will usually have a link table.

So we'd have:

PERSON
ADDRESS
PERSON_ADDRESS

The PERSON_ADDRESS table would contain person_id and address_id to link the two entities together. So one person could have many addresses, and a given address could potentially belong to more than one person or company.

For a 1:m relationship, it's good enough to have this:

PERSON
ADDRESS

In address, you would have the person_id column, but there could be many address records for a given person_id, giving you the 1:m capability.

dcp
+1  A: 

In NHibernate, it is quite simple and straight-forward. Here's how the domain classes would look, followed by fluent mappings. This assumes you would use NHibernate to generate your schema. If you are mapping a legacy database, it is simple to set the column names and table names used.

public class Championship {
  public virtual int Id { get; set; }
  public virtual IList<Match> Matches { get; set; }
}


public class Match {
  public virtual int Id { get; set; }
  public virtual Championship Champioship { get; set; }
}


public class ChampionshipMap : ClassMap<Championship> {
  public ChampionshipMap() {
    Id(x => x.Id);
    HasMany(x => x.Matches);
  }
}


public class MatchMap : ClassMap<Match> {
  public MatchMap () {
    Id(x => x.Id);
    References(x => x.Championship);
  }
}
qstarin
ok, I get it. but if I'm building DAL by hand, how can I do this? I mean, if I need to load a championship object, I need to load all it's matches, and that will require loading championships for each match, and so on... I must be missing something
chester89
If its circular references you are worrying about, garbage collection will take care of that.Obviously, you cannot require the Championship in the Match's ctor and a list of Match's in the Championship's ctor.But .. you can make the Match take a Championship in the ctor, but in the Championship initialize the List of Matches empty and then fill it with championship.Matches.Add(new Match() {...});As for your DAL, I recommend reading up on the Repository, Data Access Object (Dao), and Active Record patterns. I usually go with Dao myself.
qstarin
yes, I'm worried about circular references, thanks a lot
chester89
A: 

For example in DataObjects.Net you can write following to get automatically associated Championship.Matches entity set and Match.Championship persistent field.

[HierarchyRoot]
public class Championship : Entity
{
  [Field, Key]
  public int Id { get; set; }

  [Field, Association(PairTo="Championship")]
  public EntitySet<Match> Matches { get; private set; }
}

[HierarchyRoot]
public class Match : Entity
{
  [Field, Key]
  public int Id { get; set; }

  [Field]
  public Championship Championship { get; set; }
}
Alex Kofman