EntityFramework关系的方式

时间:2013-08-24 15:52:52

标签: c# entity-framework

如果我有一个客户进行查询(只允许一个查询)我有:

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;}
}

或者我是这样的:

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;}
}

在第一个场景中,我非常确定Inquiry是否会被删除,Customer也会被删除,除非我使用public Guid? InquiryId {get;set;}以及导航属性。这种情况确实更有意义。

在第二种情况下,我很确定如果Customer被删除,Inquiry将被删除,这是所需的效果。但它确实使导航属性有点多余,因为您希望查看客户的查询customer => inquiry,而不是客户提出的查询inquiry.FirstOrDefault(x => x.Customer.Id.Equals(customerId))

在某种程度上,Delete On Cascade属性有帮助,但导航属性是多余的,但另一方面Delete On Cascade没有帮助(并且需要更多代码才能使其有效)但导航财产是有帮助的。

那么你如何决定走哪条路呢?

认为 第一种情况的另一个缺点是,您必须手动删除相关的Inquiry,因为当您删除{{1}时它只是忽略级联(因为它已在代码中关闭)。

1 个答案:

答案 0 :(得分:1)

将您的问题和评论中的以下信息放在一起......

  • 客户只有一次查询
  • 希望当客户被删除时,也应删除相关的查询
  • 您希望客户与查询之间的关系为一对一或零

......如果没有进一步的映射规范,这两个模型都不会满足这些要求。但是,您可以通过使用第一个模型并使用Fluent API添加显式映射来实现目标:

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

相关CustomerInquiry将共享相同的主键值,即Inquiry中的主键是Customer的外键。

关于一些不正确的假设的一些评论:

  

在第一个场景中,我很确定调查是否会被删除   客户也将被删除。

这是不正确的,因为您的模型中没有外键属性,在这种情况下,EF将采用可选关系,并且默认情况下不启用级联删除。

  

在第二种情况下,我很确定客户是否会被删除   查询将被删除。

出于同样的原因不正确。

  

这是一对一或零(关系)。

您的第一个和第二个场景都代表一对多关系,因为如果您只在关系的一侧有导航属性,那么EF将假设默认关系。如果您在另一侧公开集合或不使其成为一对多关系,则无关紧要。例如,在第一个场景中,您可以让两个客户引用相同的查询,这意味着(从概念上和从数据库角度来看)此查询将有两个(= 许多)客户。