Взаимосвязь структуры сущностей, основанная на идентичном ключе

#c# #mysql #entity-framework

#c# #mysql #entity-framework

Вопрос:

Я пытаюсь выяснить, возможно ли представить менее распространенную модель в entity framework. База данных, которую я использую, содержит Persons, PersonFile, Файлы, изображения и исполняемые файлы. У пользователя может быть много файлов PERSONFILE, у каждого файла PersonFile есть один файл, а файл является либо изображением, либо исполняемым файлом (все они имеют свою собственную таблицу, но изображения / исполняемый файл разделяют свой первичный ключ с файлом, вместо того, чтобы иметь явную связь с внешним ключом)

Моя Персона выглядит примерно так:

 public class Person {

  // Properties
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  [JsonProperty("id")]
  public Guid Id { get; set; }

  public virtual ICollection<PersonFile> PersonFile { get; set; }

}

public class Person_Config : IEntityTypeConfiguration<Person> {
  public void Configure(EntityTypeBuilder<Person> entity) {
    entity.ToTable("person");

    // Properties
    entity.Property(e => e.Id)
      .HasColumnName("id");

  }
}
 

Мой PersonUploads выглядит следующим образом:

 public class PersonFile {

  // Ids
  public Guid FileId { get; set; }
  public Guid PersonId { get; set; }


  // Relations
  public virtual File File { get; set; }
  public virtual Person Person { get; set; }
}

public class PersonFile_Config : IEntityTypeConfiguration<PersonFile> {
  public void Configure(EntityTypeBuilder<PersonFile> entity) {
    entity.ToTable("_Person_File");

    entity.HasKey(e => new { e.FileId, e.PersonId });

    entity.Property(e => e.FileId)
      .HasColumnName("File_id");

    entity.Property(e => e.PersonId)
      .HasColumnName("Person_id");

    entity.HasOne(d => d.File)
      .WithMany(p => p.PersonFile)
      .HasForeignKey(d => d.FileId)
      .OnDelete(DeleteBehavior.ClientSetNull);

    entity.HasOne(d => d.Person)
      .WithMany(p => p.PersonFile)
      .HasForeignKey(d => d.PersonId)
      .OnDelete(DeleteBehavior.ClientSetNull);
  }
}
 

Моя файловая модель выглядит следующим образом:

 public class File {
  // Properties
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public Guid Id { get; set; }
  public string Type { get; set; }

  // Relations
  public virtual Image Image { get; set; }
  public virtual Executable Executable { get; set; }

  public virtual ICollection<PersonFile> PersonFile { get; set; }
}

public class File_Config : IEntityTypeConfiguration<File> {
  public void Configure(EntityTypeBuilder<File> entity) {
    entity.ToTable("File");

    // Properties
    entity.Property(e => e.Id)
      .HasColumnName("id")
      .IsRequired();

    entity.Property(e => e.Type)
      .HasColumnName("type")
      .HasMaxLength(255)
      .IsRequired();

  }
}
 

И для краткости, мой образ и исполняемые файлы выглядят почти одинаково, имеет значение только отношение каждого из них к файлу. Вот как выглядит изображение:

 public class Image {
  // Properties
  public Guid Id { get; set; }

  // Relations
  public virtual File File { get; set; }
}

public class Image_Config : IEntityTypeConfiguration<Image> {
  public void Configure(EntityTypeBuilder<Image> entity) {
    entity.ToTable("Image");

    entity.Property(e => e.Id)
      .HasColumnName("id")
      .IsRequired();

    entity.HasOne(u => u.File)
      .WithOne(r => r.Image)
      .HasForeignKey<File>(u => u.Id)
      .OnDelete(DeleteBehavior.ClientSetNull);
  }
}
 

При запросе с помощью linq я могу без проблем получить файл от пользователя, выполнив что-то вроде этого:

 ICollection<File> files_image = await (from file in db.File
                                      join image in db.Image
                                      on file.Id equals image.Id
                                      join personfile in db.PersonUpload
                                      on file.Id equals personfile.UploadId
                                      where personfile.PersonId == id
                                      select file)
                                    .ToListAsync();
 

Однако, как только я попытаюсь запросить конкретное изображение с помощью объединения и выбрать это изображение в качестве результирующего типа, например:

 ICollection<Image> files_image = await (from file in db.File
                                                  join image in db.Image
                                                  on file.Id equals image.Id
                                                  join personfile in db.PersonFile
                                                  on file.Id equals personfile.FileId
                                                  where personfile.PersonId == id
                                                  select image).ToListAsync();

 

Я получаю следующую ошибку:

 MySql.Data.MySqlClient.MySqlException (0x80004005): Unknown column 'r.PersonId' in 'field list'
 

Кто-нибудь знает, где я ошибаюсь, или как правильно моделировать такие отношения? (Я думаю, что в этом проблема, но, возможно, я полностью упускаю что-то еще) Спасибо за вашу помощь!

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

1. Вы определили свойства навигации, вы должны использовать их вместо объединений, чтобы уменьшить повторение.