[英]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.