Вот моя сущность:
public class StackImage: ICollection<StackFile>
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual Guid Id { get; set; }
private IList<StackFile> StackFiles { get; set; } = new List<StackFile>();
public StackImage()
{
}
[...] // Implementation of ICollection
}
public class StackFile
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual Guid Id { get; set; }
public string Url { get; set; }
public int Position { get; set; }
public StackFile(){}
}
stackImage.Add(new StackFile(url));
stackImage= await _stackImageRepository.UpdateAsync(stackImage);
await _unitOfWork.SaveChangesAsync();
В этом примере после UpdateAsync идентификатор StackImage не создается (stackImage.Id == по умолчанию), но идентификатор StackFile создается правильно (stackImage [0] .Id == по умолчанию)
Вы уже заметили эту проблему? Я предполагаю, что EF Core видит StackImage как список и не пытается создать новый Guid. Как исправить эту проблему?
РЕДАКТИРОВАТЬ: Из того, что я могу прочитать в Интернете, и из полученных мной ответов, кажется, что это невозможно. Если у кого-то есть решение, дайте нам знать :)
Почему бы просто не следовать стандартам EF и не раскрыть общедоступное свойство ICollection<StackFile>
, а не реализовать интерфейс?
Это длинное объяснение. Самая короткая версия: у меня может быть ОДНО изображение или НЕСКОЛЬКО изображений. Итак, я создал унаследованный абстрактный класс MEDIA. Нужно время, чтобы подумать о модели, это решение было наиболее эффективным для того, что мы хотели. Но если EF Core не может с этим справиться, да, я буду использовать общедоступную коллекцию. Поколение миграции сработало хорошо. Я подожду нескольких предложений и посмотрю, что лучше всего сделать. Спасибо за вашу помощь
Мне кажется, что вы хотите создать базу данных с (как минимум) двумя таблицами. Стол с StackImages
и стол с StackFiles
.
Вы хотите создать отношение «один ко многим» между StackImages
и StackFiles
: каждый StackImage
имеет ноль или более StackFiles
, каждый StackFile
принадлежит ровно одному StackImage
. В базе данных это реализовано с помощью внешнего ключа.
Следовательно, неверно, что StackImage является StackFile. Однако вы можете сказать, что у StackImage есть несколько файлов StackFiles.
Следуя Соглашения о первом коде фреймворка сущности, ваши классы должны быть похожи на:
class StackImage
{
public Guid Id {get; set;}
...
// every StackImage has zero or more StackFiles (one-to-many):
public virtual ICollection<StackFile> StackFiles {get; set;}
}
class StackFile
{
public Guid Id {get; set;}
...
// every StackFile belongs to exactly one StackImage, using foreign key:
public Guid StackImageId {get; set;}
public virtual StackImage StackImage {get; set;}
}
наконец, DbContext:
class MyDbcontext : DbContext
{
public DbSet<StackImage> StackImages {get; set;}
public DbSet<StackFile> StackFiles {get; set;}
}
Обратите внимание на использование виртуальных свойств для выражения отношений между таблицами. Поскольку внешний ключ StackImageId
должен быть реальным столбцом, он не виртуальный.
In entity framework the columns of a table are represented by non-virtual properties, the virtual properties represent the relations between the tables.
Поскольку я следовал соглашениям, нет необходимости ни в атрибутах, ни в свободном API. Entity framework обнаруживает коллекцию «один ко многим» и создает для вас подходящие таблицы. Только если вам нужны разные идентификаторы для ваших таблиц или столбцов, вам понадобится свободный API или атрибуты.
Спасибо за действительно полный ответ, я знаю соглашение, но я хотел попробовать что-то еще в нашем контексте веб-API. Сформировать то, что я могу прочитать в Интернете, но ответы, которые я получил здесь, кажется невозможным.
это список (или, по крайней мере, коллекция), и поэтому он не может быть представлен строкой в какой-либо таблице. Следовательно, ему также не нужно свойство PK.