If I understand correctly, you're trying to create a One:Many optional relationship between ClassA
and ClassB
. It also sounds like you always want ClassB
to have an associated ClassA
, which would make ClassA
your principal, and ClassB
your dependant.
Firstly, you'll have to change your navigation property for ClassB
(in your ClassA
). Since you want a many relationship, you'll need some kind of collection to store your ClassB
objects.
This means you'll remove your MaybeKey
in ClassA
, as there isn't a single object that you're referring to, instead you now have a collection (e.g. ICollection<ClassB>
). You also won't need a column in the corresponding ClassA
table to refer to ClassB
(because it's a one-many relation, a single column wouldn't work). There should only need to be a foreign key column in the ClassB
table, referring to the ClassA
to which the ClassB
is related.
Your code could look like this:
public class ClassA
{
[Key]
public int Key { get; set; } // ClassA Key
public virtual ICollection<ClassB> MyClassBs { get; set; } // Your optional dependants.
}
public class ClassB
{
[Key]
public int Key { get; set; } // ClassB key
public int AKey { get; set; } // Your foreign key.
public virtual ClassA myClassA { get; set; } // Your principal.
}
The navigation properties are marked virtual
so Entity Framework can override them, and provide you with lazy-loading functionality (if you require it).
To create your mapping, you'd do something along these lines (might need some alteration if I've misunderstood your goal).
modelBuilder.Entity<ClassA>()
.HasMany(b => b.MyClassBs) // Many ClassBs
.WithRequired(a => a.myClassA) // Each ClassB requires a ClassA
.HasForeignKey(b => b.AKey); // Use Akey as a foreign key
There are a few different ways to express this (e.g. you could do it from the ClassB
side).
It might be worth sticking to a slightly more conventional naming e.g ID
for the primary keys and names like ClassAID
for your foreign keys, as Entity framework has a number of default conventions you can make use of. It also makes it slightly easier for others to read your code (as you tend to encounter similar conventions).
Edit: Updated to include "Special" relationship.
In your ClassA
you can include the following fields (which you already had in your original example, with different names):
public int SpecialBID { get; set; }
public virtual ClassB SpecialB { get; set; }
and add the following mapping:
modelBuilder.Entity<ClassA>()
.HasOptional(x => x.SpecialB)
.WithMany()
.HasForeignKey(x => x.SpecialBID);
Although there is now no guarantee that your SpecialB
is included in your MyClassBs
collection.
You should also be able to remove the MyClassBs collection entirely from ClassA, by using a relationship mapping that doesn't require a navigation property on the other side of the relationship (in the classB object):
modelBuilder.Entity<ClassB>()
.HasRequired(x => x.myClassA)
.WithMany()
.HasForeignKey(x => x.AKey);