Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何创建一个具有复合键的表,其中每个成员都是其他表的外键成员_C#_Entity Framework_Ef Code First_Data Annotations_Ef Fluent Api - Fatal编程技术网

C# 如何创建一个具有复合键的表,其中每个成员都是其他表的外键成员

C# 如何创建一个具有复合键的表,其中每个成员都是其他表的外键成员,c#,entity-framework,ef-code-first,data-annotations,ef-fluent-api,C#,Entity Framework,Ef Code First,Data Annotations,Ef Fluent Api,我正在尝试在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")]

我正在尝试在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; }
}
我认为我在这里的意图相当明显。我有顾客。那些顾客有车。我想创建一个CustomerAppoints表,其中一位客户和其中一位客户的车辆计划进行服务

为了记录在案,这并不是整个模型,为了问题的目的,已经对其进行了简化

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

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

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.
我尝试过不同的注释,甚至尝试过使用fluent 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);

}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has必需(ca=>ca.Customer)
.WithRequiredPrincipal()
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(ca=>ca.Vehicle)
.WithRequiredPrincipal()
.WillCascadeOnDelete(假);
}
但是我不能让它工作。我已经阅读了谷歌上能找到的每一个样本,但没有结果


PS…如果这只适用于注释,那将是我的首选。

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

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

[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; }
}
记住也要删除fluent映射

如果依赖实体上的外键不可为空,则代码 首先在关系上设置级联删除。如果在 依赖实体可为空,代码优先不设置级联删除 在关系上,以及当主体被删除时,外键 将设置为空


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

删除
客户时,您的模型有两个从
客户
客户应用
的级联删除路径:

  • 客户
    ->
    车辆
    ->
    客户应用
  • 客户
    ->
    客户申请
这在SQL Server中是不允许的,会导致异常。您需要为这三个子路径中的至少一个子路径禁用级联删除,这只有在Fluent API中才可能实现。例如
客户
->
车辆
路径:

modelBuilder.Entity<Vehicle>()
    .HasRequired(v => v.Customer)
    .WithMany()
    .HasForeignKey(v => v.CustomerId)
    .WillCascadeOnDelete(false);
modelBuilder.Entity()
.has必需(v=>v.Customer)
.有很多
.HasForeignKey(v=>v.CustomerId)
.WillCascadeOnDelete(假);
您还可以将
CustomerId
设为null,使其具有可选关系,在这种情况下,默认情况下EF将禁用级联删除。但将required关系更改为optional关系表示业务规则的更改,我不会仅仅为了避免fluentapi而这样做


顺便问一下:
customerappoint
应该有一个复合主键,这真的正确吗?这意味着,一个拥有给定车辆的特定客户只能预约一次服务。同一客户/车辆组合在不同的预约日期不能有很多预约吗?如果是,您应该为
CustomerAppoint
CustomerId
VehicleId
使用一把单独的钥匙,而不是主键的一部分。

强烈反对,“代码优先”是一个更好的选择,可以轻松处理此问题。在这种情况下,它不起作用,因为
CustomerId
VehicleId
是主键的一部分,您不能将其设为null。@Slauma更正,感谢您指出这一点。正如你在回答中所说,使用复合键是很奇怪的。+1,因为我刚刚键入了类似的内容,但这更具说服力;这也证实了我没有疯。