Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有两个独立表和一个从属表的多个一对一关系_C#_Entity Framework_Ef Fluent Api - Fatal编程技术网

C# 具有两个独立表和一个从属表的多个一对一关系

C# 具有两个独立表和一个从属表的多个一对一关系,c#,entity-framework,ef-fluent-api,C#,Entity Framework,Ef Fluent Api,我已经读了很多关于这个话题的相关问题,但是没有一个能解决我的问题,所以请耐心听我说。 我是EF的新手,尝试在ASP.NET MVC中使用EF6建立以下关系: 我需要两张固定的桌子,司机和汽车。现在,当一个驾驶员与一辆汽车关联时,我需要在这些表之间创建一个关系但只能为一辆车分配一名驾驶员。 驾驶员可能并不总是与汽车相关联,反之亦然,我希望维护这两个表,即使它们之间并不总是有关联,因此我认为我需要一个额外的表专门用于建立此连接。我认为这将在这些类之间建立1:1:1的关系 下面是我的POCO类的模型

我已经读了很多关于这个话题的相关问题,但是没有一个能解决我的问题,所以请耐心听我说。 我是EF的新手,尝试在ASP.NET MVC中使用EF6建立以下关系:

我需要两张固定的桌子,司机和汽车。现在,当一个驾驶员与一辆汽车关联时,我需要在这些表之间创建一个关系但只能为一辆车分配一名驾驶员。

驾驶员可能并不总是与汽车相关联,反之亦然,我希望维护这两个表,即使它们之间并不总是有关联,因此我认为我需要一个额外的表专门用于建立此连接。我认为这将在这些类之间建立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配置关系,但我认为我完全错了,因为我遇到了以下错误:

在上引入外键约束“FK_dbo.DriverCar_dbo.Car_CarId” 表'DriverCar'可能导致循环或多个级联路径。具体说明 删除不操作或更新不操作,或修改其他外部 关键制约因素。无法创建约束或索引。见前文 错误

流畅的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);
modelBuilder.Entity()
.HasRequired(a=>a.Driver)
.with可选(s=>s.DriverCar)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(a=>a.Car)
.with可选(s=>s.DriverCar)
.WillCascadeOnDelete(假);
我真的不确定我是否遗漏了什么,或者是否有更好的方法来处理这种情况,如果有人能给我一些关于如何解决这个问题的反馈,我将不胜感激


更新 我在这里找到了一个有趣的答案: 我相信这正是我想要的:0..1对0..1的关系。但所有提到的选项似乎都太复杂了,我不太确定哪一个是最好的,甚至不知道如何正确地实现它们

在EF中,这些类型的关系应该很难实现吗?
例如,我尝试了选项1,但它从两个表中创建了0..1对多关系-驾驶员对汽车和汽车对驾驶员。那么,我该如何在它们之间创建一个独特的关联呢?

请为您的模型尝试此方法。虚拟启用延迟加载,并建议使用导航属性。显示外键的数据注释(或使用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);
公共类驱动程序
{
public int DriverID{get;set;}
公共字符串名称{get;set;}
//其他附加字段
公共驱动器CAR?驱动器CAR{get;set;}
}
公车
{
public int CarID{get;set;}
公共字符串品牌{get;set;}
//其他附加字段
公共驱动器CAR?驱动器CAR{get;set;}
}
公共类驱动程序
{
public int DriverCarID{get;set;}
[外国钥匙(“司机”)]
public int DriverID{get;set;}
公共驱动程序{get;set;}
[外国钥匙(“汽车”)]
public int CarID{get;set;}
公共小汽车{get;set;}
}
modelBuilder.Entity()
.has可选(a=>a.DriverCar)
.WithRequired(s=>s.Driver)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.has可选(a=>a.DriverCar)
.需要(s=>s.Car)
.WillCascadeOnDelete(假);

注意:更改为外键的数据注释。倒装流利的语句。修正了驾驶员与汽车之间的第二种关系。

这里有一个简单的方法来创建一对零的关系。请注意,我是一个将所有表的Id保持为Id的粉丝,而不是CarId等,这只是我的风格。这只是一个控制台应用程序,因此一旦添加EF nuget,您就可以进行复制/粘贴

但是下面的代码与.NETFramework4.6和EF6.2配合使用,它创建了以下表格

汽车

  • Id(主键,整数,非空)
  • 驱动程序Id(FK、int、null)
司机

  • Id(主键,整数,非空)
在这种模式下,一辆汽车只能有一名驾驶员。尽管如此,一名驾驶员仍可能驾驶多辆车。我不确定这是否是你的问题

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

        }
    }
使用System.Data.Entity;
命名空间EFTest
{
班级计划
{
静态void Main(字符串[]参数)
{
var connectionString=“”;
var context=新数据库上下文(connectionString);
var car=新车();
var driver=新驱动程序();
context.Cars.Add(car);
context.Drivers.Add(驱动程序);
汽车司机=司机;
SaveChanges();
}
}
公车
{
公共int Id{get;set;}
公共虚拟驱动程序{get;set;}
}
公务舱司机
{
公共int Id{get;set;}
}
公共类DatabaseContext:DbContext、IDatabaseContext
{
公共数据库集车辆{get;set;}
公共数据库集驱动程序{get;set;}
公共数据库上下文(字符串connectionString):基(connectionString){}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasKey(n=>n.Id)
.has可选(n=>n.Driver);
modelBuilder.Entity()
.HasKey(n=>n.Id);
}
}
}
但是,如果您真的想强制每个汽车和驾驶员只有一个映射的约束,您可以使用下面的代码来实现。注意,w
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();
    }

}