0

我正在尝试首先在 MVC 项目上使用注释(第一次)编写代码。

我创建了以下 POCO。

[Table("Customers")]
public partial class Customer
{
    public int Id { get; set; }

    [Required]
    [DisplayName("First Name")]
    public string FirstName { get; set; }

    [DisplayName("Last Name")]
    [Required]
    public string LastName { get; set; }
    //other properties...
 }

[Table("Vehicles")]
public partial class Vehicle
{
    [Required]
    public int Id { get; set; }

    [Required]
    public int CustomerId { get; set; }

    [Required]
    public string Make { get; set; }

    [Required]
    public string Model { get; set; }

    [Required]
    public string Year { get; set; }

    //other fields
    [ForeignKey("CustomerId")]
    public virtual Customer Customer { get; set; }
}


[Table("CustomerAppointments")]
public partial class CustomerAppointment
{

    [Key,Column(Order=0)]
    public int CustomerId { get; set; }

    [Key,Column(Order=1)]
    public int VehicleId { get; set; }

    public DateTime? AppointmentDate { get; set; }

    public DateTime? AppointmentTime { get; set; }

    public string AvailableDays { get; set; }

    //other fields

    [ForeignKey("CustomerId")]
    public virtual Customer Customer { get; set; }

    [ForeignKey("VehicleId")]
    public virtual Vehicle Vehicle { get; set; }
}

我认为我在这里的意图是相当明显的。我有客户。这些客户有车辆。我想创建一个表 CustomerAppointments,其中安排了一个客户和其中一个客户车辆进行服务。

作为记录,这不是整个模型,并且出于问题的目的进行了简化。

我正在使用 MvcScaffolding 构建 EF 项目和视图。

一切都编译但是当我尝试导航到客户页面(实际上是一个没有提到引用客户的类)时,我收到以下错误......

Introducing FOREIGN KEY constraint 'FK_dbo.CustomerAppointments_dbo.Vehicles_VehicleId' on table 'CustomerAppointments' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

我尝试了不同的注释,甚至尝试使用流利的 API 与这样的东西......

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<CustomerAppointment>()
        .HasRequired(ca => ca.Customer)
        .WithRequiredPrincipal()
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<CustomerAppointment>()
        .HasRequired(ca => ca.Vehicle)
        .WithRequiredPrincipal()
        .WillCascadeOnDelete(false);

}

但我无法让它工作。我已经阅读了可以在 google 和 SO 上找到的所有示例,但无济于事。

PS ...如果这只能与注释一起使用,那将是我的偏好。

4

3 回答 3

2

您的模型有两个级联删除路径,从删除aCustomer到删除 a :CustomerAppointmentCustomer

  • Customer-> Vehicle->CustomerAppointment
  • Customer->CustomerAppointment

SQL Server 中不允许这样做并导致异常。您需要对这三个子路径中的至少一个禁用级联删除,这只能通过 Fluent API 实现。例如Customer->Vehicle路径:

modelBuilder.Entity<Vehicle>()
    .HasRequired(v => v.Customer)
    .WithMany()
    .HasForeignKey(v => v.CustomerId)
    .WillCascadeOnDelete(false);

您还可以使CustomerIdnullable 具有可选关系,在这种情况下,EF 将默认禁用级联删除。但是将 required 更改为可选关系表示业务规则的更改,我不会仅仅为了避免 Fluent API 而这样做。

CustomerAppointment顺便说一句:应该有一个复合主键真的正确吗?这意味着拥有给定车辆的给定客户只能预约一次服务。同一客户/车辆组合在不同的约会日期不能有很多约会吗?如果是,您应该为 and 设置一个单独的键,并且CustomerAppointment只是外键而不是主键的一部分。CustomerIdVehicleId

于 2013-07-19T22:31:52.710 回答
0

似乎您最好使用数据库优先方法,然后使用 ado enity 数据模型生成模型。

于 2013-07-19T21:05:23.250 回答
0

按照惯例,级联删除是通过在模型中引入实际外键来处理的。如果您使用不可为空的外键,则需要删除。使用可为空的外键将其关闭。

通过使外键可以为空,将您的类更改为以下内容:

[Table("CustomerAppointments")]
public partial class CustomerAppointment
{

    [Key,Column(Order=0)]
    public int? CustomerId { get; set; }

    [Key,Column(Order=1)]
    public int? VehicleId { get; set; }

    public DateTime? AppointmentDate { get; set; }

    public DateTime? AppointmentTime { get; set; }

    public string AvailableDays { get; set; }

    //other fields

    [ForeignKey("CustomerId")]
    public virtual Customer Customer { get; set; }

    [ForeignKey("VehicleId")]
    public virtual Vehicle Vehicle { get; set; }
}

请记住还要删除流利的映射。

来自http://msdn.microsoft.com/en-US/data/jj679962

如果依赖实体上的外键不可为空,则 Code First 会在关系上设置级联删除。如果依赖实体上的外键可以为空,Code First 不会在关系上设置级联删除,并且当主体被删除时,外键将设置为空。

于 2013-07-19T21:02:16.503 回答