Callum Linington
Callum Linington

Reputation: 14417

EntityFramework Relationship which way round

If I have a customer which makes an inquiry (only one inquiry allowed) do I have:

public class Customer
{
    public string Name {get;set;}
    public string ContactNumber {get;set;}

    public virtual Inquiry Inquiry {get;set;}
}
public class Inquiry
{
    public string Product {get;set;}
    public string Information {get;set;}
    public string Reason {get;set;}
}

or do I have it like this:

public class Customer
{
    public string Name {get;set;}
    public string ContactNumber {get;set;}
}
public class Inquiry
{
    public string Product {get;set;}
    public string Information {get;set;}
    public string Reason {get;set;}

    public virtual Contact Contact {get;set;}
}

In the first scenario, I'm pretty sure if an Inquiry gets deleted the Customer will also get deleted, unless I use public Guid? InquiryId {get;set;} as well as the navigation property. This scenario does make more sense.

In the second scenario, I'm pretty sure if a Customer gets deleted the Inquiry will be deleted which is the desired effect. But it does make the navigation property a little redundant because you want to see what Enquiry a Customer has made customer => inquiry, rather then what Inquiries has a Customer made inquiry.FirstOrDefault(x => x.Customer.Id.Equals(customerId)).

In one way the Delete On Cascade property helps but the navigation property is redundant, however in the other way Delete On Cascade doesn't help (and needs more code to make it work in favour) but the navigation property is helpful.

So how do you decide which way to go?

I think the other downside to the first scenario, is that you have to manually delete the related Inquiry because when you delete the Customer it just ignores the cascade (because it has been turned off in code).

Upvotes: 0

Views: 77

Answers (1)

Slauma
Slauma

Reputation: 177133

Putting the following infos from your question and your comments together...

  • A customer has a single inquiry
  • The effect is desired that when a customer gets deleted the related inquiry should be deleted as well
  • You expect the relationship between customer and inquiry to be one-to-one or zero

...neither of the two models will fulfill these requirements without further mapping specification. However, you can achieve the goal by using the first model and adding an explicit mapping with Fluent API:

modelBuilder.Entity<Customer>()
    .HasOptional(c => c.Inquiry)
    .WithRequired()
    .WillCascadeOnDelete(true);

Related Customer and Inquiry will share the same primary key value, i.e. the primary key in Inquiry is the foreign key to Customer.

A few remarks about some incorrect assumptions:

In the first scenario, I'm pretty sure if an Inquiry gets deleted the Customer will also get deleted.

That's not correct because you don't have foreign key properties in your model in which case EF will assume an optional relationship and doesn't enable cascading delete by default.

In the second scenario, I'm pretty sure if a Customer gets deleted the Inquiry will be deleted.

Not correct for the same reason.

It's a one-to-one or zero (relationship).

Both your first and your second scenario represent one-to-many relationships because that's the default relationship EF will assume if you have a navigation property only on one side of the relationship. It doesn't matter if you expose a collection on the other side or not to make it a one-to-many relationship. For example in the first scenario you could have two customers refering to the same inquiry which means that (conceptually and from database viewpoint) this inquiry will have two (= many) customers.

Upvotes: 1

Related Questions