« first day (529 days earlier)      last day (2502 days later) » 

A K
10:18 PM
@PashaPash Спасибо за ответ
Попробовал позаполнять таблицы данными, плюс потестировать разные запросы в linqpad'е типа наиболее частых:

var cars = this.Car
.Include(x => x.PrimaryImage)
.ToList();

var car = this.Car
.Include(x => x.AllImages)
.FirstOrDefault(x => x.ID == 1);
Ну... оно работает, этого у него точно не отнять
(Причём реально совпало с тем решением, которое мне уже дали на en-so -- я специально сравнивал структуру базы)
Правда, я не могу сказать, что понимаю механику как оно работает под капотом... для меня до сих пор магия, где здесь какие пары какое отношение описывают и какие были убраны за ненадобностью.
Как ни считаю -- в моих версиях всё парно, всё хорошо. А как у вас получается -- почему-то выглядит неправильно, но зато работает как надо.
И я ещё успел прочитать замечание по то, что отношение 0 к 0..1 не описать в реляционных терминах. (Я где-то уже читал подобное, не помню где) Вот это тоже звучит любопытно и непонятно.
Потому что я как раз глядя в ssms всё время считаю лишним столбец Car_ID (FK, int, null) -- он всегда пустой и ненужный
 
A K
10:42 PM
Если я правильно понимаю, то
первая связь (машина может иметь несколько изображений) - это пара полей:
на Cars:
public virtual ICollection<CarImage> AllImages { get; set; }
на CarsImage:
public virtual Car Car { get; set; }
вторая связь (машина может иметь 0..1 заглавных изображений) -- это пара полей:
на Cars:
public virtual CarImage PrimaryImage { get; set; }
на CarsImage:
public virtual Car CarWithPrimaryImage { get; set; }
при этом мы можем убрать безболезненно Car с CarsImage в первом отношении (EF оно не требуется для понимания что это за тип связи) и можем убрать CarWithPrimaryImage во втором отношении (EF также понимает, что за тип связи)
При этом я не создавал вообще CarWithPrimaryImage (оно будет совпадать с Car) да и сам Car действительно (пока?) не нужен в запросах.
Попытка явного объявления CarWithPrimaryImageID приводит к созданию ещё одного столбца:
А вот если убрать и CarWithPrimaryImageID и Car -- то выходит более простая и ожидаемая структура:
но она неправильная: при попытке вставить что-либо -- теряется информация о привязках картинок к машинам
А, ну это из-за того, что я из класса CarImage не только public virtual Car Car { get; set; } удалил но ещё и public int CarID { get; set; }
В общем, и CarID (FK, int, not null) и Car_ID (FK, int, null) оба нужны, как бы ни хотелось отказаться от какого-то одного из них
Тестовый набор такой был всё время:
var car1 = new Car { PrimaryImage = null, PrimaryImageID = null, Title = "Volga" };
this.Car.Add(car1);
this.SaveChanges();

var carImage1 = new CarImage { CarID = car1.ID, FileName = "volga1" };
this.CarImage.Add(carImage1);
this.SaveChanges();

var carImage2 = new CarImage { CarID = car1.ID, FileName = "volga2defalut" };
this.CarImage.Add(carImage2);
car1.PrimaryImage = carImage2;
this.SaveChanges();

var car2 = new Car { PrimaryImage = null, PrimaryImageID = null, Title = "Bently" };
this.Car.Add(car2);
 
A K
11:17 PM
И вот наконец итоговый вариант, который ПОЛНОСТЬЮ подходит по всем показателям:
public class Car
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

[Required]
public string Title { get; set; }

public int? PrimaryImageID { get; set; }

[ForeignKey("PrimaryImageID")]
public virtual CarImage PrimaryImage { get; set; }

[ForeignKey("CarID")]
public virtual ICollection<CarImage> AllImages { get; set; }
}
public class CarImage
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

[Required]
public int CarID { get; set; }

public string FileName { get; set; }
}
 

« first day (529 days earlier)      last day (2502 days later) »