2

When using Entity Framework, I get confused as to where I need to define a relationship between two entities. I feel like whenever I look for examples, I end up finding examples of the same thing from two different perspectives - dependent → principal, as well as principal → dependent.

Given the following entities:

class Foo
{
    public int Id { get; set; }
    public virtual ICollection<Bar> Bars { get; set; }
}

class Bar
{
    public int Id { get; set; }
    public Foo Foo { get; set; }
    public virtual Baz { get; set; }
}

class Baz
{
    public int Id { get; set; }
    public Bar Bar { get; set; }
}

We have several scenarios here. Foo has many Bars pointing to it. Baz has an optional foreign key to Bar. Baz can exist without Bar specified.

Where would I defined these relations? By where, I mean when using fluent API, which entity would these relations be defined in relation to? Maybe to make it more clear, if I were using fluent API and EntityTypeConfiguration classes for binding, for which entity would these be defined in?

An example of why I'm confused is because I see answers like this one that say that a one-to-one should be defined in the class with the virtual. So in these entities, the optional one-to-one between Baz and Bar would be, or something similar to:

modelBuilder.Entity<bar>()
            .HasOptional(f => f.Baz)
            .WithRequired(s => s.Bar);
Community
  • 1
  • 1
Ryan
  • 867
  • 9
  • 23

2 Answers2

2

I think you are confused by the virtual keyword. I did try to find it on the page you linked to, but it's not there.

The virtual keyword lets the Entity Framework override that property in a proxy entity that it creates behind the scenes and which inherits from Bar. The override will then make a database call to lazy load Baz when the property is accessed.

The virtual keyword has nothing to do with the definition of the relationship, and if you don't want lazy loading, you don't need it.

You define the principal when you map:

modelBuilder.Entity<bar>()
            .HasOptional(f => f.Baz). //Baz is dependent
            .WithRequired(s => s.Bar);//Bar is principal

modelBuilder.Entity<bar>()
            .HasOptional(f => f.Bar). //Bar is dependent
            .WithRequired(s => s.Baz);//Baz is principal

As for the other relationship in your example between Foo and Bar, Foo has a collection of Bars but Foo has only one Bar so the foreign key goes on Bar. EF will do that by default.

The dependent gets the foreign key that references the principal's key. When it's a one to one, that foreign key is also the dependent's primary key but EF can't work out which is which and that's why you get an error until you've specified it.

Reference: http://msdn.microsoft.com/en-us/library/ee382827.aspx

Colin
  • 22,328
  • 17
  • 103
  • 197
2

when you use EF as you defined in your classes you already defined you relations. EF has the ability to understand that when you define you navigation properties in Collection in a class

public virtual ICollection<Bar> Bars { get; set; }

that you want one to many Relation.

On the other hand if you add a collection to the other class

public virtual ICollection<Foo> Foos { get; set; }

EF will understand that you want Many to may Relation

same thing will happen if you add an instance of class as property in the other class it will understand that as one to one (or zero to one ) relation.

virtual keyword has nothing to do with your relation as mentioned before, it concerned in lazy, eager loading

Eiaddar
  • 180
  • 1
  • 13