Добавление коллекции принадлежащих объектов

#c# #ef-core-2.2 #owned-types

#c# #ef-core-2.2 #принадлежащие типы

Вопрос:

У меня есть модель предметной области с коллекцией принадлежащих типов. Когда я пытаюсь добавить более одного объекта в коллекцию ownedtyped? Я получаю исключение:

Система.Исключение InvalidOperationException: ‘Экземпляр объекта типа ‘ChildItem’ не может быть отслежен, поскольку другой экземпляр со значением ключа ‘{NameID: -2147482647, Id: 0}’ уже отслеживается. При замене принадлежащих объектов измените свойства без изменения экземпляра или сначала отсоедините предыдущую запись принадлежащего объекта.’

Как это можно решить?

ОБНОВЛЕНО

Классы моего домена:

 public class Parent
    {
        public int Id { get; set; }
        public Child Name { get; set; }
        public Child ShortName { get; set; }
    }

    public class Child
    {
        public List<ChildItem> Items { get; set; }
    }

    public class ChildItem
    {
        public string Text { get; set; }
        public string Language { get; set; }
    }
  

Мой DbContext:

 public class ApplicationContext : DbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Parent>()
                .OwnsOne(c => c.Name, d =>
                {
                    d.OwnsMany(c => c.Items, a =>
                    {
                        a.HasForeignKey("NameId");
                        a.Property<int>("Id");
                        a.HasKey("NameId", "Id");
                        a.ToTable("ParentNameItems");
                    })
                    .ToTable("ParentName");
                })
                .ToTable("Parent");

                modelBuilder.Entity<Parent>()
                .OwnsOne(c => c.ShortName, d =>
                {
                    d.OwnsMany(c => c.Items, a =>
                    {
                        a.HasForeignKey("NameId");
                        a.Property<int>("Id");
                        a.HasKey("NameId", "Id");
                        a.ToTable("ParentShortNameItems");
                    })
                    .ToTable("ParentShortName");
                })
                .ToTable("Parent");
        }
    }
  

Использование:

 static void Main(string[] args)
        {
            var context = new ApplicationContext();

            var parent = new Parent()
            {
                Name = new Child()
                {
                    Items = new List<ChildItem>()
                    {
                        new ChildItem() { Text = "First value", Language = "en-en"},
                        new ChildItem() { Text = "Second value", Language = "en-en"}
                    }
                },
                ShortName = new Child()
                {
                    Items = new List<ChildItem>()
                    {
                        new ChildItem() { Text = "First short value", Language = "en-en"},
                        new ChildItem() { Text = "Second short value", Language = "en-en"}
                    }
                }
            };

            context.Set<Parent>().Add(parent);

            context.SaveChanges();
        }
  

Ответ №1:

Ну, во-первых, ваши классы не имеют смысла. Во всяком случае, это должно быть

 public class Parent
{
    public int Id { get; set; }
    public List<Child> Children { get; set; }
}
  

у родителя должно быть много дочерних элементов (или, возможно, ни одного, может быть, пустой список?). А как насчет имени и идентификатора дочернего элемента, разве у него нет по одному из них? также, возможно, родительский идентификатор, может быть, что-то вроде

 public class Child
{
    public virtual List<ChildItem> Items { get; set; } //why virtual? you planning to inherit?
    public string Name {get; set; }
    public int Id {get; set; }
    public int ParentId {get; set; }
}
  

Я должен думать, что это выглядит немного лучше. В базе данных должны быть соответствующие таблицы. и давайте будем честны, автоматическое создание EF (Entity Framework) сделает 99% работы за вас, поэтому, пожалуйста, используйте его.

Комментарии:

1. Спасибо за быстрый ответ! Чтобы быть ближе к моей реальной ситуации, я внес некоторые обновления в код.

Ответ №2:

Проблема решена. Это было в строке

 a.HasKey("NameId", "Id");
  

в OnModelCreating методе.
Я использовал пример, где было написано о настройке коллекций принадлежащих типов.

После удаления поля «NameID» из определения ключа

 a.HasKey("Id");
  

теперь все работает нормально.