It's actually me
It's actually me

Reputation: 502

How to write EF Code first mapping for Child with Many Parent Types scenario

I have 4 Classes. Supplier, Customer, Employee, and Address. Any of the first 3 types can have "n" number of addresses. So the classes looks like this;

class Address 
{
    int Id { get; set; }
    int ParentId { get; set; }  // NOTE: This is the FK.
    IAggregateRoot Parent { get; set; } // EXAMPLE: Supplier, Customer, Employee ..

    // rest of the address fields.
}

class Supplier : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the supplier details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

class Customer : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the customer details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

class Employee : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the employee details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

How to write the mapping for the Address's Parent attribute? Or a better approach/design to do this kinda scenario?

Upvotes: 1

Views: 342

Answers (3)

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59151

From comments on the OP:

I didn't want to have many Address classes for each Parent type. No I do not want query/navigate from Address to Parent.

Is there something in your domain logic or user workflows that will make multiple parents sharing the same address a real scenario? As in, will the fact that addresses are shared ever show up in the UI in an important way unless they both log in and swap info face to face?

If not, I'm not sure it really matters if two identical addresses share the same ID or not, and I'm not sure the potential data duplication matters.

In which case I recommend KISS.

Make three separate mapping tables, don't bother with any inheritance, and call it done :)

SupplierToAddressMap:
SupplierId  AddressId

CustomerToAddressMap:
CustomerId  AddressId

EmployeeToAddressMap:
EmployeeId  AddressId

Upvotes: 0

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364409

If Employee, Customer and Supplier don't share parent entity (class) and don't follow inheritance mapping you cannot do that. Your address must have separate relation for each related entity as @olivehour mentioned.

Upvotes: 0

danludwig
danludwig

Reputation: 47375

How do you expect EF to solve a mapping like this in the db? Would the Address.ParentId column reference the primary key of Customer, Supplier, or Employee?

You might be able to do it if you get rid of the navigation from the Address to the IAggregateRoot. Perhaps try this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Employee>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("EmployeeId"));
    modelBuilder.Entity<Supplier>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("SupplierId"));
    modelBuilder.Entity<Customer>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("CustomerId"));
}

Upvotes: 2

Related Questions