9:47 AM
10:22 AM
2 hours later…
11:55 AM
@Uranus Не побудете немного моим утёнком? Вижу, вы немного заинтересовались вопросом, а я сейчас как раз структурирую свои мысли перед написанием ответа, как экстраверту мне проще это делать хоть с воображаемым, но собеседником.
Мы на работе называем эту разновидность утёнка "черепом Йорика": достаточно молчать или изредка угукать ))
Так вот, следите за руками, сейчас будет показана последовательность как идти к правильному ответу, а не шарахаться наобум.
public class CarImage
{
[Key]
public int ID { get; set; }
public string FileName { get; set; }
[Required]
public int CarID { get; set; }
[ForeignKey("CarID")]
public virtual Car Car { get; set; }
}
{
[Key]
public int ID { get; set; }
public string FileName { get; set; }
[Required]
public int CarID { get; set; }
[ForeignKey("CarID")]
public virtual Car Car { get; set; }
}
public class Car
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
public class CarImage
{
[Key]
[ForeignKey("Car")]
public int ID { get; set; }
[Required]
public int CarID { get; set; }
[ForeignKey("CarID")]
public virtual Car Car { get; set; }
public string FileName { get; set; }
}
{
[Key]
[ForeignKey("Car")]
public int ID { get; set; }
[Required]
public int CarID { get; set; }
[ForeignKey("CarID")]
public virtual Car Car { get; set; }
public string FileName { get; set; }
}
public class Car
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public virtual CarImage PrimaryImage { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public virtual CarImage PrimaryImage { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
Мне тут не очень нравится автоматическое название ключа в базе, которое делает EF по умолчанию (добавляет лишнее подчёркивание), поэтому я напишу это вот в таком виде:
public class Car
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public int? PrimaryImageID { get; set; }
[ForeignKey("PrimaryImageID")]
public virtual CarImage PrimaryImage { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public int? PrimaryImageID { get; set; }
[ForeignKey("PrimaryImageID")]
public virtual CarImage PrimaryImage { get; set; }
public virtual ICollection<CarImage> AllImages { get; set; }
}
Что ещё? Помимо моего варианта, в котором всё расписано явно (а явное всегда лучше неявного) можно не вешать [ForeignKey("Car")] на таблицу CarImages -- в этом была прелесть ответа, данного мне на en-so: EF достаточно умён и понимает сам, что нужно делать.
Я правда не захотел это решение не потому что оно неявно что-то проделало (я этого ещё не понимал), а мне очень не понравился дополительный столбец в базе. Сильно не понравился
И нашёл на свою голову вариант, когда навешивал [Required] на виртуальное свойство. С ним "компилировалось", даже структура базы была похожей на правду -- но возникали проблемы со вставкой в базу. Код ошибки я вам скидывал, а суть была такая (если смотреть в отладчике), что при записи в CarImage он вставлял в CarID значение первичного ключа картинки (скажем, 1853) и это же значение пытался вставить в первичный ключ CarImage.ID -- хотя должен был вставить автоинтерментом единицу.
12:39 PM
var car1 = new Car { PrimaryImage = null, PrimaryImageID = null, Title = "Mercedes" };
this.Car.Add(car1);
this.SaveChanges();
var carImage1 = new CarImage { CarID = car1.ID, Car = car1, FileName = "asdf1" };
this.CarImage.Add(carImage1);
this.SaveChanges();
this.Car.Add(car1);
this.SaveChanges();
var carImage1 = new CarImage { CarID = car1.ID, Car = car1, FileName = "asdf1" };
this.CarImage.Add(carImage1);
this.SaveChanges();
A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'ID'.
При этом мы не можем использовать "двухходовку" и сначала вставить картинку без привязки к машине, чтобы потом указать в машине заглавную картинку:
var car1 = new Car { PrimaryImage = null, PrimaryImageID = null, Title = "Mercedes" };
this.Car.Add(car1);
this.SaveChanges();
var carImage1 = new CarImage { CarID = null, Car = null, FileName = "asdf1" };
this.CarImage.Add(carImage1);
this.SaveChanges();
car1.PrimaryImage = carImage1;
car1.PrimaryImageID = carImage1.ID;
carImage1.Car = car1;
carImage1.Car.ID = car1.ID;
this.SaveChanges();
this.Car.ToList().Dump();
this.CarImage.ToList().Dump();
this.Car.Add(car1);
this.SaveChanges();
var carImage1 = new CarImage { CarID = null, Car = null, FileName = "asdf1" };
this.CarImage.Add(carImage1);
this.SaveChanges();
car1.PrimaryImage = carImage1;
car1.PrimaryImageID = carImage1.ID;
carImage1.Car = car1;
carImage1.Car.ID = car1.ID;
this.SaveChanges();
this.Car.ToList().Dump();
this.CarImage.ToList().Dump();
Что вообще очевидно: CarID не может быть пуст, картинка обязана быть привязана к какой-то конкретной машине
вторая проблема -- невозможно почистить таблицу Car от прежних экспериментов, которые я делал в linqpad'е
« first day (526 days earlier) ← previous day next day → last day (2505 days later) »
Transcript for
Jan21
Jan '1722
Jan23
Дискуссии о C#/.NET на русском
Эта комната посвящена обсуждению C#: всё, что не подходит в фо...