Почему ядро ​​EF пытается добавить навигационное свойство в БД, а не только идентификатор сторонней модели? - PullRequest
0 голосов
/ 14 мая 2019

Мне было интересно, почему EF пытается добавить и иностранные модели. Пример:

public class Category
{
    public int Id { get; set; }
    public string Name{ get; set; }
}

public class Content
{
    public int Id { get; set; }
    public string Name{ get; set; }
    public Category Category{ get; set; }
}

После создания «Контента» с помощью миграций у меня есть таблица, которая содержит идентификатор категории. Это создать. Итак, у меня есть три столбца: Id, name и categoryId. Кажется, EF «знает», что это должен быть только первичный ключ Category, который нужно сохранить.

Чем я пытался что-то добавить с помощью EF.

var cat = new Category {Id = 2, Name = "awesomeCat"})
var addContent = new Content({Name = "test", Category = cat})

Теперь я хочу добавить Контент с помощью _context.Add (addContent). Я ожидал одну вставку в базу данных, которая использует имя «test» и categoryId 2. Id будет сгенерирован DB.

Но вместо этого EF также пытается добавить новую категорию в таблицу категорий.

Итак, я посмотрел глубже и, похоже, EF «не знает», что он уже существует, и не поддерживал транзакции, касающиеся модели категории. Я сделал еще одну попытку и не использовал новую категорию, вместо этого я загружал ее раньше: var cat = _context.findById ("2"); и назначил этот вместо. Теперь EF должен знать, что он уже существует и не должен добавлять его в таблицу категорий.

Может быть, моя модель просто не права. Нужно ли использовать его больше как:

public class Content
{
    public int Id { get; set; }
    public string Name{ get; set; }
    public int? CategoryId{ get; set; }
    [ForeignKey("CategoryId")]
    public Category Category{ get; set; }
}

Разве я не получу две ссылки на категории?

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

EF Core имеет внутреннее отслеживание сущностей.Когда вы просто создаете новую категорию, она не отслеживается.Когда вы добавляете контент, EF также будет отслеживать любые связанные объекты, которые будут включать вашу категорию, которая по умолчанию будет отслеживаться как «Добавленная».У вас есть несколько вариантов.

  1. Не «обновляйте» существующую категорию, а скорее извлекайте ее из базы данных.Если EF извлекает его из базы данных, он будет отслеживаться и больше не будет добавляться.

  2. Вы можете явно отслеживать экземпляр категории, который вы обновили, и установить его состояние равным «Не изменено».".

    _context.Attach(category);
    _context.Entry(category).State = EntityState.Unchanged;
    _context.Add(content);
    
  3. Лучший способ - вообще не работать со свойством reference и использовать явное свойство внешнего ключа.Добавьте свойство к своему классу контента:

    public int CategoryId { get; set; }
    

    Затем вы можете просто установить этот идентификатор вместо Category prop:

    var addContent = new Content { Name = "test", CategoryId = 2 };
    

    EF будет заполнять ссылочное свойство после того, каксохранить.

0 голосов
/ 14 мая 2019

Вы должны указать EF Core, что это первичный ключ, и сгенерировать ключ

public class Category
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Content
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
    public Category Category { get; set; }
}

Тогда вам не нужно отмечать [ForeignKey ("CategoryId")], EF Core превратит ссылку на объект в идентификатор в базе данных

Если я неправильно понял ваш вопрос, спросите еще раз:)

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