Исключение InvalidCastException при добавлении объекта в DbSet

#c# #entity-framework

#c# #entity-framework

Вопрос:

У меня есть два класса

 [Table("Kunden")]
public class Kunde
{

    public Guid Id { get; set; }
 

    [Required, ForeignKey("Id")]
    public virtual List<Standort> OrtStandort { get; set; }

    
    public Kunde()
    {
        Id = Guid.NewGuid();
        OrtStandort = new List<Standort>();
    }
}

[Table("Standorte")]
public class Standort
{
    public Guid Id { get; set; }

    public Standort()
    {
        Id = Guid.NewGuid();
        //KontaktAnsprechpartner = new List<Ansprechpartner>();
    }
}

public class HausarbeitContext : DbContext
{
    public DbSet<Kunde> Kunden { get; set; }
    
    public DbSet<Standort> Standort { get; set; }
    
    // ...
}
         
         
         
  

Как только отладчик нажмет:

  haDB/*HausarbeitContext*/.Kunden/*DbSet<Kunde>*/.Add(kunde);
  

Я получаю:

Система.InvalidCastException: ‘Das Objekt des Typs «System.Коллекции.Generic.List`1[ClassDesigner.Part_Hausarbeit.Data.Standort]» kann nicht in Typ «ClassDesigner.Part_Hausarbeit.Data.Standort» umgewandelt werden.’ (не может быть преобразован)

Смотрите объект: введите описание изображения здесь

Ответ №1:

Возможно, вам потребуется включить полные определения для 2 объектов. На первый взгляд, выделяется одна вещь: // Knude

 [Required, ForeignKey("Id")]
public virtual List<Standort> OrtStandort { get; set; }
  

Атрибут ForeignKey обычно применяется на стороне «Один» Много-к-одному. Кроме того, хотя я не считаю, что это требование, ссылки на коллекции обычно объявляются как ICollection<T> , а не List<T> . EF будет стремиться установить прокси для virtual участников, поэтому желательно оставить эти ссылки в качестве типа интерфейса более низкого уровня.

Учитывая отношение Kunde amp; Standort parent-children, ссылки FK обычно будут:

 public class Kunde
{
     [Key]
     public Guid Id { get; set; }

     public virtual ICollection<Standort> OrtStandort { get; set; } = new List<Standort>();
}

public class Standort
{
    [Key]
    public Guid Id { get; set; }
    
    public Guid KundeId { get; set; }
    [ForeignKey("KundeId")]
    public virtual Kunde Kunde { get; set; }
}
  

FK для отношения Kunde-Standort управляется на стороне Многих для единственного столбца идентификатора, указывающего обратно на родительский.

Или, чтобы исключить KundeId свойство внутри стандартной сущности, используя теневое свойство (ядро EF) или сопоставляя его без определения поля, используемого Map(x => x.MapKey("KundeId")) в EF 6.

Кроме того, при использовании идентификаторов Guid для ключевых столбцов я бы настоятельно рекомендовал использовать подход, созданный базой данных (помечая столбцы как Identity ), а не устанавливать в коде, а затем настроить их на использование последовательной генерации идентификаторов GUID. Например, с SQL Server, используя NEWSEQUENTIALID() вместо NEWID() :

 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
  

Если вам нужно установить их в коде, я бы рассмотрел варианты генерации идентификатора GUID удобным для индексации способом для выбранной вами базы данных и внедрил генератор идентификаторов Guid, который может упорядочивать различные элементы, составляющие идентификатор GUID, чтобы индексация базы данных могла эффективно сортировать их. Рандомизированный по умолчанию идентификатор .Net GUID приведет к значительной фрагментации индексной таблицы. В системах, которые могут видеть более 10 тысяч строк, это может привести к значительным проблемам с использованием памяти / диска и производительности.

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

1. ‘Kunde’ по-немецки означает: ‘Customer’, а ‘Kunden’ — множественное число.

2. Исправлено написание. Во время посещения Германии я обнаружил, что мое произношение немецкого языка даже хуже, чем мое правописание. : D