Let's say I have two entity objects "table" and "chicken."
Now let's say, I have a "wing" object, and I want that wing to have a 0..1-1 relationship with table and chicken. In otherwords, I want a nullable table.wing and a nullable chicken.wing.
Is there a good way, using Entity Framework 4, to make the wing object have the restriction that it can either be associated with a table OR a chicken?
Note: I don't want to have a wingedobjects baseclass in my dictionary- this needs to be a "has one" not an "is one."
My thought is that I can't make a unique restraint on the collection of references, so I'll have to wrap the Entity properties with something like:
public partial class Wing:
...
public Table Table
{
get { return this.Table; }
set {
//make sure Chicken is null
this.Table = value;
}
}
...
}
This strikes me as pretty hacky and not too clean, so I was looking for a better, if not best, practices solution.
Edit:
To be clear, I currently have a 0..1-1 relationship between table and wing, and a 0..1-1 relationship between chicken and wing. Thus, I can create a table.wing and I can then look at wing.table. What I want is to ensure that I ALWAYS have a null value if I query table.wing.chicken or chicken.wing.table. The wing must be associated with EITHER one table OR one wing.
In response to @morganppdx's comment:
Given this Entity Diagram:
And the following in Program.cs:
class Program
{
static void Main(string[] args)
{
Model1Container container = new Model1Container();
Wing chickenwing = new Wing { Shape = "birdlike" };
Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
Table table1 = new Table { Style = "Mission", Wing = chickenwing }; // Should throw exception!
container.AddToChickens(chicken1);
container.AddToTables(table1);
container.SaveChanges();
Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
Console.ReadLine(); //wait for input to give us time to read
}
}
The resulting console will show:
Table 1's wing has a birdlike shape...Table 1 has Andalusian chicken wings!
This result is what I wish to avoid. It should throw an exception when chickenwing is associated with table1 because it is already associated with chicken1, and cannot be associated with both a table and with a chicken.
It is quite possible that I am building the relationship incorrectly, and thus not getting @morganpdx's stated exception where I want it.
The code is available at: https://github.com/mettadore/WingThing
Off the top of my head, my suggestion would be to create child objects that extend the Wing object, and use those instead of your Wing object:
public class ChickenWing : Wing
{
public Table Table { get { throw new NoTablesAllowedException; }}
}
public class TableWing: Wing
{
public Chicken Chicken { get { throw new NoChickensHereException; }}
}
The code you posted would then look like this:
class Program
{
static void Main(string[] args)
{
Model1Container container = new Model1Container();
ChickenWing chickenwing = new ChickenWing { Shape = "birdlike" };
TableWing tablewing = new TableWing { Shape = "circular" };
Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
Table table1 = new Table { Style = "Mission", Wing = tablewing };
container.AddToChickens(chicken1);
container.AddToTables(table1);
container.SaveChanges();
Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
Console.ReadLine(); //wait for input to give us time to read
}
}
I have not done anything like this to date, but I believe this should work. Essentially the Wing object acts as an Interface to describe the ChickenWing and TableWing objects, but those are discreet objects used for discreet purposes.