aidrivenpost
aidrivenpost

Reputation: 1943

One to many relationship Fluent API Code First

This is my first question, I hope is not a dumb one.

I have the following entities here

Customer Companies Phones

public class Customers 
{
    public Customers()
    {
        Phones = new List<Phones>();
    }

    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Phones> Phones { get; set; }
}
public class Phones
{
    public Guid Id { get; set; }
    public string Number { get; set; }
    public string Extension { get; set; }

}

public class Companies
{
    public Companies()
    {
        Phones = new List<Phones>();
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<Phones> Phones { get; set; }        
}

I want to created with the fluent api a one to many relationship between phones and the same with company and phones.

Upvotes: 1

Views: 9459

Answers (3)

000
000

Reputation: 806

What you need is what I call association table, you need to make EF create a separate table to hold the relationship details. I do not know if EF is able to do that or not. But in case you are ok with changing your object model then one solution could be to designate specific types for those tables.

public class CustomerPhone
{
    public int Id { get; set; }
    public Customers Customer { get; set; }
    public Phones Phone { get; set; }
}
public class CompanyPhone
{
    public int Id { get; set; }
    public Companies Company { get; set; }
    public Phones Phone { get; set; }
}

Now this classes could hold the relationship, so now you can replace Phone with them:

public class Customers
{
    public Customers()
    {
        Phones = new List<CustomerPhone>();
    }

    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<CustomerPhone> Phones { get; set; }
}
public class Companies
{
    public Companies()
    {
        Phones = new List<CompanyPhone>();
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<CompanyPhone> Phones { get; set; }
}

This way you have the opportunity to add more details to your relationship, like creation date etc..

Upvotes: 1

Slauma
Slauma

Reputation: 177133

I am not sure if you want the following:

modelBuilder.Entity<Customers>()
    .HasMany(c => c.Phones)
    .WithOptional()
    .Map(m => m.MapKey("CustomerPhoneId"));

modelBuilder.Entity<Companies>()
    .HasMany(c => c.Phones)
    .WithOptional()
    .Map(m => m.MapKey("CompanyPhoneId"));

Using MapKey is optional. It just gives the foreign key column the name you want. If you omit this EF will create a standard name (something with underscore: ..._Id).

In fact the whole mapping is optional because the mapping conventions will just create the same relationships without any Fluent API mapping at all.

The Phones table will have two nullable foreign keys CustomerPhoneId and CompanyPhoneId refering to Customers table and Companies table respectively.

Edit

An alternative which would only require one foreign key in the Phone table for multiple different entities would be an inheritance mapping:

public abstract class OrganizationsWithPhone
{
    public OrganizationsWithPhone()
    {
        Phones = new List<Phones>();
    }

    public Guid Id { get; set; }
    public ICollection<Phones> Phones { get; set; }
}

public class Customers : OrganizationsWithPhone
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Companies : OrganizationsWithPhone
{
    public string Name { get; set; }
}

public class Phones
{
    public Guid Id { get; set; }
    public string Number { get; set; }
    public string Extension { get; set; }
}

Mapping:

modelBuilder.Entity<OrganizationsWithPhone>()
    .HasMany(o => o.Phones)
    .WithOptional() // or .WithRequired()
    .Map(m => m.MapKey("OrganizationsWithPhoneId"));

modelBuilder.Entity<OrganizationsWithPhone>()
    .ToTable("OrganizationsWithPhone");

modelBuilder.Entity<Customers>()
    .ToTable("Customers");

modelBuilder.Entity<Companies>()
    .ToTable("Companies");

Now you have only one foreign key relationship between Phones and the base table OrganizationsWithPhone, but due to the inheritance mapping there are additional one-to-one relationships between the base table and the tables for the derived entities Customers and Companies. Basically the number of necessary relationships stays the same (or is even one more in this model).

In this model a customer and a company cannot share the same phone numbers because a row in the Phones table refers to an OrganizationsWithPhone which can either be a customer or a company but not both at the same time.

The base table OrganizationsWithPhone has only a single column Id. If you have more common properties in all derived entities you can move them into the base entitiy.

Upvotes: 6

tdykstra
tdykstra

Reputation: 6050

See this tutorial -- there are 1 to many relationships between Instructor and Department, between Course and Entrollment, and between Student and Enrollment which you can use as models:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application

Upvotes: 0

Related Questions