我已经阅读了很多与此主题相关的问题,但是似乎都没有解决我的问题,因此请耐心等待。 我是EF的新手,并尝试使用EF6在ASP .NET MVC中建立以下关系:
我需要有两个永久性表,Drivers和Cars。现在,当驾驶员与汽车相关联时,我需要在这些表之间创建关系。 但是只能将一名驾驶员分配给一辆汽车。
驾驶员不一定总是与汽车相关联,反之亦然,即使它们之间并不总是具有关联性,我也希望维护两个表,因此我认为我需要专门拥有一个附加表建立连接。我认为这将在这些类之间创建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配置关系,但是我相信这样做是完全错误的,因为遇到了以下错误:
在上引入FOREIGN KEY约束'FK_dbo.DriverCar_dbo.Car_CarId' 表“ DriverCar”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN 关键约束。无法创建约束或索引。见前 错误。
Fluent 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到许多关系-驾驶员到汽车和汽车到驾驶员。那我该如何在它们之间创建唯一的关联?
答案 0 :(得分:1)
为您的模型尝试一下。 Virtual启用延迟加载,建议使用其导航属性。显示外键(或使用流利)的DataAnnotation,以确保每个关系都使用正确的键。
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);
注意:更改为外键的数据注释。流畅的陈述倒转。修复了驾驶员与汽车之间处于第二种关系。
答案 1 :(得分:0)
这是创建一对零的一种简单方法。请注意,我喜欢将所有表的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();
}
}
}