简体   繁体   English

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

[英]How do I create a table that has a composite key each member of which is a foreign key member to other tables

I am trying to do code first with annotations (for the first time) on an MVC project. 我试图在MVC项目上首先使用注释(第一次)来编写代码。

I have created the following POCOs. 我创建了以下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; }
}

I think my intent here is fairly obvious. 我认为我的意图非常明显。 I have customers. 我有客户。 Those customers have vehicles. 那些客户有车辆。 I want to create a table CustomerAppointments where a customer and one of the customers vehicles is scheduled for a service. 我想创建一个CustomerAppointments表,其中客户和一个客户车辆被安排用于服务。

For the record, this is not the whole model and has been simplified for the purposes of the question. 为了记录,这不是整个模型,并且为了问题的目的已经简化。

I am using MvcScaffolding to build out the EF items and the views. 我正在使用MvcScaffolding来构建EF项目和视图。

Everything compiles but when I try to navigate to the Customers page (actually a class not mentioned that references customers) I am getting the following error... 一切都编译但当我尝试导航到客户页面(实际上是一个未提及引用客户的类)时,我收到以下错误...

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.

I have tried different annotations and even tried to use the fluent API with something like this... 我尝试过不同的注释,甚至尝试使用这样的流程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);

}

But I cannot get it to work. 但我无法让它发挥作用。 I have read every sample I can find on google and SO but to no avail. 我已经阅读了我可以在Google和SO上找到的每个样本,但无济于事。

PS...if this can work with Annotations only that would be my preference. PS ...如果这可以使用注释只是我的偏好。

Your model has two cascading delete paths from Customer to CustomerAppointment when a Customer is deleted: 你的模型有两个级联删除从路径CustomerCustomerAppointmentCustomer被删除:

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

That's not allowed in SQL Server and causes the exception. 这在SQL Server中是不允许的并导致异常。 You need to disable cascading delete for at least one of those three subpaths which is only possible with Fluent API. 您需要为这三个子路径中的至少一个禁用级联删除,这只能通过Fluent API实现。 For example the Customer -> Vehicle path: 例如Customer - > Vehicle路径:

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

You could also make CustomerId nullable to have an optional relationship in which case EF will disable cascading delete by default. 您还可以使CustomerId空而具有可选关系,在这种情况下,EF将默认禁用级联删除。 But changing a required to an optional relationship expresses a change in business rules which I wouldn't do just to avoid Fluent API. 但是将所需关系更改为可选关系表示业务规则的更改,我不会仅仅为了避免使用Fluent API。

BTW: Is it really correct that CustomerAppointment should have a composite primary key? 顺便说一句: CustomerAppointment应该有一个复合主键是否真的正确? It would mean that a given customer with a given vehicle could only have one service appointment. 这意味着具有给定车辆的给定客户只能有一个服务预约。 Couldn't there be many appointments for the same customer/vehicle combination at different appointment dates? 在不同的预约日期,相同的客户/车辆组合是否有很多预约? If yes, you should rather have a separate key for CustomerAppointment and CustomerId and VehicleId would be just foreign keys without being part of the primary key. 如果是,您应该为CustomerAppointmentCustomerId分别使用单独的密钥,而VehicleId只是外键而不是主键的一部分。

By convention, cascade deletes are handled by the introduction of the actual foreign key into your model. 按照惯例,通过将实际外键引入模型来处理级联删除。 If you use a non-nullable foreign key, it will require delete. 如果使用不可为空的外键,则需要删除。 Use a nullable foreign key to turn it off. 使用可以为空的外键将其关闭。

Change your class to the following by making the foreign keys nullable: 通过使外键可为空来将您的类更改为以下内容:

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

Remember to also remove the fluent mapping. 请记住也删除流畅的映射。

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

If a foreign key on the dependent entity is not nullable, then Code First sets cascade delete on the relationship. 如果依赖实体上的外键不可为空,则Code First会在关系上设置级联删除。 If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null. 如果依赖实体上的外键可以为空,则Code First不会在关系上设置级联删除,并且当删除主体时,外键将设置为null。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何以编程方式复制具有复合键的MS Access表架构? - How do I programmatically copy MS Access table schema which has composite key? 我如何播种具有外键的表,该表在模型中被指定为对象,但在表中被指定为GUID - How do i seed a table that has a foreign key, which is specified as an object in the model, but as a guid in the table 如何创建一个DbSyncForeignKeyConstraint到表具有复合主键 - how do I create a DbSyncForeignKeyConstraint to a table with a composite Primary Key 如何在Entity Framework中创建由外键组成的复合主键? - How can I create a composite primary key consisting of foreign keys to two tables in Entity Framework? 如何在 EF Core 中拥有外键和其他属性的复合键? - How can I have a composite key of a foreign key and other properties in EF Core? 将具有复合键/外键的表映射到该表 - Map table with composite key / foreign key to that table 如何在 Entity Framework Core 中创建由基类和派生类组合而成的复合键 - How do I create composite key which is combination of base class and derived class in Entity Framework Core 如何编写处理与用C#中的外键连接的表的Web API? - How do I write a Web api which deals with tables that are connected with a foreign key in c#? 从外键和DateTime创建复合键 - Create composite key from foreign key and DateTime 如果表中有外键,如何在表中插入信息? - How do I insert information in a SQL table if the table has a foreign key in it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM