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 ...如果這隻適用於註釋,那隻會是我的偏好。

回答

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不會在關係上設置級聯刪除 ,並且在刪除委託人時,外鍵 將設置爲null。

+0

在這種情況下它不起作用,因爲'CustomerId'和'VehicleId'是主鍵的一部分,不能爲空。 – Slauma

+0

@Slauma更正,謝謝你指出。正如你在答案中所述,奇怪的是擁有這個組合鍵。 –

0

看起來您最好使用數據庫優先方法,然後使用ado enity數據模型生成模型。

+2

非常不贊同,代碼優先是一個更好的選擇,並且可以輕鬆地處理這個問題 –

2

你的模型有兩個級聯刪除Customer路徑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); 

你也可以將CustomerId爲空的有一個可選的關係,在這種情況下,EF將禁用級聯默認情況下刪除。但是,將需求更改爲可選關係表達了​​業務規則的變化,我不會僅僅爲了避免使用Fluent API。

順便說一句:CustomerAppointment應該有一個複合主鍵是真的嗎?這意味着給定車輛的客戶只能有一個服務預約。在不同的約會日期,是否有相同客戶/車輛組合的約會?如果是的話,你應該有一個單獨的密鑰CustomerAppointmentCustomerIdVehicleId只是外鍵而不是主鍵的一部分。

+0

+1,因爲我只是在輸入類似的東西,但這更具說服力;這也證實我並不瘋狂。 – Chris

相關問題