[英]Multiple one-to-one relationship with two independent tables and one dependent
我已經閱讀了很多關於這個主題的相關問題,但它們似乎都沒有解決我的問題,所以請耐心等待。 我是 EF 的新手,並嘗試在 ASP .NET MVC 中使用 EF6 建立以下關系:
我需要有兩個永久表,Drivers 和 Cars。 當 Driver 與 Car 關聯時,我現在需要在這些表之間創建關系。 但是一個 Driver 只能分配給一個 Car。
Driver 可能並不總是與 Car 相關聯,反之亦然,即使它們之間並不總是存在關聯,我也想維護這兩個表,所以這就是為什么我認為我需要一個額外的表來專門做這個聯系。 我認為這將在這些類之間創建 1:1:1 的關系。
以下是我的 POCO 課程的模型。
楷模
public class Driver
{
public int DriverID { get; set; }
public string Name { get; set; }
//other additional fields
public DriverCar DriverCar { get; set; }
}
public class Car
{
public int CarID { get; set; }
public string Brand { get; set; }
//other additional fields
public DriverCar DriverCar { get; set; }
}
public class DriverCar
{
public int DriverCarID { get; set; }
public int DriverID { get; set; }
public Driver Driver { get; set; }
public int CarID { get; set; }
public Car Car { get; set; }
}
我已經嘗試使用 Fluent API 配置關系,但我相信我做錯了,因為我遇到了以下錯誤:
在表 'DriverCar' 上引入 FOREIGN KEY 約束 'FK_dbo.DriverCar_dbo.Car_CarId' 可能會導致循環或多個級聯路徑。 指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 約束。 無法創建約束或索引。 請參閱以前的錯誤。
流利的API
modelBuilder.Entity<DriverCar>()
.HasRequired(a => a.Driver)
.WithOptional(s => s.DriverCar)
.WillCascadeOnDelete(false);
modelBuilder.Entity<DriverCar>()
.HasRequired(a => a.Car)
.WithOptional(s => s.DriverCar)
.WillCascadeOnDelete(false);
我真的不確定我是否遺漏了什么,或者是否有更好的方法來處理這種情況,如果有人能給我一些關於如何解決這個問題的反饋,我將不勝感激。
剛剛在這里找到了一個有趣的答案: Is it possible to capture a 0..1 to 0..1 relationship in Entity Framework? 我相信這正是我想要的:0..1 到 0..1 的關系。 但是所有提到的選項似乎都太復雜了,我不太確定哪一個是最好的,或者如何正確實施它們。
這些類型的關系應該在 EF 中很難實現嗎? 例如,我嘗試了選項 1,但它從兩個表中創建了一個 0..1 到多的關系 - Driver to Car 和 Car to Driver。 那么我該如何在它們之間創建獨特的關聯呢?
為您的模型試試這個。 Virtual 啟用延遲加載並建議用於導航屬性。 DataAnnotations 顯示外鍵(或使用 fluent)以確保每個關系使用正確的鍵。
public class Driver
{
public int DriverID { get; set; }
public string Name { get; set; }
//other additional fields
public DriverCar? DriverCar { get; set; }
}
public class Car
{
public int CarID { get; set; }
public string Brand { get; set; }
//other additional fields
public DriverCar? DriverCar { get; set; }
}
public class DriverCar
{
public int DriverCarID { get; set; }
[ForeignKey("Driver")]
public int DriverID { get; set; }
public Driver Driver { get; set; }
[ForeignKey("Car")]
public int CarID { get; set; }
public Car Car { get; set; }
}
modelBuilder.Entity<Driver>()
.HasOptional(a => a.DriverCar)
.WithRequired(s => s.Driver)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Car>()
.HasOptional(a => a.DriverCar)
.WithRequired(s => s.Car)
.WillCascadeOnDelete(false);
注意:更改為外鍵的數據注釋。 倒置流暢的語句。 在第二個關系中固定驅動程序到汽車。
這是創建從一到零的簡單方法。 請注意,我喜歡將所有表的 Id 保持為 Id,而不是 CarId 等,只是我的風格。 這只是一個控制台應用程序,因此一旦您添加了 EF nuget,您就可以復制/粘貼。
但是下面的代碼適用於 .net framework 4.6 和 EF6.2 它創建了下表
車
司機
在這種模式下,一輛汽車只能有一個司機。 不過,一個司機仍然可以駕駛多輛汽車。 我不確定這對你來說是否有問題。
using System.Data.Entity;
namespace EFTest
{
class Program
{
static void Main(string[] args)
{
var connectionString = "<your connection string>";
var context = new DatabaseContext(connectionString);
var car = new Car();
var driver = new Driver();
context.Cars.Add(car);
context.Drivers.Add(driver);
car.Driver = driver;
context.SaveChanges();
}
}
public class Car
{
public int Id { get; set; }
public virtual Driver Driver { get; set; }
}
public class Driver
{
public int Id { get; set; }
}
public class DatabaseContext : DbContext, IDatabaseContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Driver> Drivers { get; set; }
public DatabaseContext(string connectionString) : base(connectionString){ }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasKey(n => n.Id)
.HasOptional(n => n.Driver);
modelBuilder.Entity<Driver>()
.HasKey(n => n.Id);
}
}
}
但是,如果您真的想對每個汽車和駕駛員強制執行僅一個映射的約束,則可以使用以下代碼來實現。 請注意,當您擁有加入實體時,您不會將其 Id 放在已加入實體的任何位置。
using System.Data.Entity;
namespace EFTest
{
class Program
{
static void Main(string[] args)
{
var connectionString = "your connection string";
var context = new DatabaseContext(connectionString);
//Create a car, a driver, and assign them
var car = new Car();
var driver = new Driver();
context.Cars.Add(car);
context.Drivers.Add(driver);
context.SaveChanges();
var assignment = new DriverAssignment() { Car_id = car.Id, Driver_Id = driver.Id };
context.DriverAssignments.Add(assignment);
context.SaveChanges();
//Create a new car and a new assignment
var dupCar = new Car();
context.Cars.Add(dupCar);
context.SaveChanges();
var dupAssignment = new DriverAssignment() { Car_id = dupCar.Id, Driver_Id = driver.Id };
context.DriverAssignments.Add(dupAssignment);
//This will throw an exception because it will violate the unique index for driver. It would work the same for car.
context.SaveChanges();
}
}
public class Car
{
public int Id { get; set; }
}
public class Driver
{
public int Id { get; set; }
}
public class DriverAssignment
{
public int Car_id { get; set; }
public int Driver_Id { get; set; }
}
public class DatabaseContext : DbContext, IDatabaseContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Driver> Drivers { get; set; }
public DbSet<DriverAssignment> DriverAssignments { get; set; }
public DatabaseContext(string connectionString) : base(connectionString) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>().HasKey(n => n.Id);
modelBuilder.Entity<Driver>().HasKey(n => n.Id);
modelBuilder.Entity<DriverAssignment>().HasKey(n => new { n.Car_id, n.Driver_Id });
modelBuilder.Entity<DriverAssignment>().HasIndex(n => n.Car_id).IsUnique();
modelBuilder.Entity<DriverAssignment>().HasIndex(n => n.Driver_Id).IsUnique();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.