Несколько взаимосвязей один-к-одному с двумя независимыми таблицами и одной зависимой - PullRequest
0 голосов
/ 26 октября 2018

Я прочитал много связанных вопросов по этой теме, но ни один из них, похоже, не решил мою проблему, поэтому, пожалуйста, потерпите меня.Я новичок в EF и пытаюсь установить следующие отношения в ASP .NET MVC с использованием EF6:

Мне нужно иметь две постоянные таблицы, Drivers и Cars.Теперь мне нужно создать связь между этими таблицами, когда водитель связан с автомобилем. Но один водитель может быть назначен только одному автомобилю.

Водитель не всегда может быть связан с автомобилем, и наоборот, и я хочу сохранить обе таблицы, даже если их нетмежду ними всегда есть связь, поэтому я считаю, что мне нужна дополнительная таблица исключительно для этой связи.Я думаю, что это создаст отношения 1: 1: 1 между этими классами.

Ниже приведена модель для моих классов POCO.

Models

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' onТаблица «DriverCar» может вызывать циклы или несколько каскадных путей.Укажите 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);

Я действительно не уверен, что я что-то упустил или есть какой-то лучший способ справиться с этимСитуация, и я был бы очень признателен, если кто-то может дать мне отзыв о том, как решить эту проблему.


Обновление

Только что нашел интересный ответ здесь: Возможно лизахватить отношения от 0..1 до 0..1 в Entity Framework? Что я считаю именно тем, что я хочу: отношение от 0.1 до 0..1.Но все перечисленные варианты кажутся слишком сложными, и я не совсем уверен, какой из них лучший или как их правильно реализовать.

Предполагается, что эти типы отношений так сложно реализовать в EF?Например, я попробовал вариант 1, но он создал отношение 0..1 ко многим из обеих таблиц - водитель с автомобилем и автомобиль с водителем.Как мне тогда создать между ними уникальную ассоциацию?

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Вот простой способ создать ноль. Обратите внимание, что я фанат сохранения идентификатора всех таблиц как просто Id, а не CarId и т. Д., Только в моем стиле. Это просто консольное приложение, поэтому после добавления натива EF вы можете просто скопировать / вставить.

Но приведенный ниже код работает с .net framework 4.6 и EF6.2. Создает следующие таблицы

Car

  • Id (PK, int, not null)
  • Driver_Id (FK, int, null)

Драйвер

  • Id (PK, int, not null)

По этой схеме автомобиль может иметь только одного водителя. Водитель может по-прежнему вести несколько автомобилей. Я не уверен, является ли это проблемой для вас или нет.

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

        }
    }

Но если вы ДЕЙСТВИТЕЛЬНО хотели применить ограничение только одного сопоставления для каждого автомобиля и водителя, вы можете сделать это с помощью приведенного ниже кода. Обратите внимание, что когда у вас есть присоединяющаяся сущность, вы не помещаете ее идентификатор в присоединяемые сущности.

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

}

}

0 голосов
/ 26 октября 2018

Попробуйте это для своих моделей. Virtual позволяет выполнять отложенную загрузку и рекомендуется для свойств навигации. DataAnnotations, показывающие использование внешних ключей (или свободное владение), чтобы убедиться, что в каждом отношении используется правильный ключ.

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

Примечание. Изменены аннотации данных для внешних ключей. Перевернутые беглые высказывания. Исправлена ​​ошибка, при которой водитель связывался с автомобилем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...