EF Core 3.1.7 Tablodaki birden çok 1: 1 ilişki için veri ek açıklamaları

Aug 17 2020

EF Core 3.11.7'nin bunu anlaması ve bir geçiş oluşturabilmesi için birden fazla 1: 1 ilişkiyi eşlemek için veri ek açıklamalarını anlamada sorunlar yaşıyorum.

Bir Kişi masam ve bir Notlar tablom var. Kişi'de 0: M Notes ilişkisi vardır. Bir kişi kaydında 0 veya daha fazla not olabilir.

Notlar tablosunda, bir Kişi olan bir CreatedBy alanı vardır. Aynı zamanda bir kişi olan LastEditedBy alanına da sahiptir. EF, Note.CreatedBy için ilişkinin nasıl kurulacağı konusunda bombalamaya devam ediyor. Bu EF değilse, her iki alan da uygun kişi kaydının Kişi Kimliği ile girilir. Tercihen Veri Ek Açıklamaları ile bunu EF Core'a nasıl açıklar?

Bir geçiş oluşturmaya çalıştığımda başarısız oluyor ve diyor ki: System.InvalidOperationException: 'Person' türündeki 'Note.CreatedBy' gezinti özelliği tarafından temsil edilen ilişki belirlenemiyor. İlişkiyi manuel olarak yapılandırın veya "[Eşleştirilmemiş]" özniteliğini kullanarak veya "OnModelCreating" içindeki "EntityTypeBuilder.Ignore" öğesini kullanarak bu özelliği göz ardı edin.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using System.Threading.Tasks;

namespace VetReg.Domain.Model
{
    public class Family
    {
        public int FamilyID { get; set; } = -1;
        public string FamilyName { get; set; }
        public List<Pet> Pets { get; set; } = new List<Pet>();
        public List<PersonFamily> People { get; set; }
        public int AddressID { get; set; } = -1;
        public List<Note> Notes { get; set; }
    }

    public class Person
    {
        public int PersonID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public DateTime? Birthdate { get; set; }
        public string Password { get; set; }
        public List<PersonFamily> Families { get; set; }
        public List<Note> Notes { get; set; }
    } // class People

    public class Note
    {
        public int NoteID { get; set; }

        public int CreatedByID { get; set; }

        [ForeignKey("CreatedByID")]
        public Person CreatedBy { get; set; }
        public DateTime DateCreated { get; set; }

        public int LastEditByID { get; set; }

        [ForeignKey("LastEditByID")]
        public Person LastEditBy { get; set; }
        public DateTime? LastEditDate { get; set; }
        public string NoteText { get; set; }
    }

    public class PersonFamily
    {
        public int PersonID { get; set; }
        public int FamilyID { get; set; }
        public Person Person { get; set; }
        public Family Family { get; set; }
    }

}

Yanıtlar

IvanStoev Aug 17 2020 at 15:11

Soru şudur (ve EF'in ilişkileri otomatik olarak belirlemesini imkansız kılan şey budur) Person.Notesve Note.CreatedBy/ Note.LastEditBy- muhtemelen hiçbiri arasındaki ilişki nedir? M arasındaki ilişki: Sen 0 olduğunu söyledim Personve Note- kişiyle ilişkili notları, 3 FKS kişiye, potansiyel olarak potansiyel müşteriler tarafından düzenlendi kişi ve notlar yarattığı notlar, ama orada 3 bire çok ilişkiler olabileceğini ifade notu Nottaki Kişi.

Ayrıca navigasyon özelliklerinden hiçbirinin gerekli olmadığını, ancak mevcut olduklarında eşleştirilmeleri gerektiğini unutmayın.

3 ilişki istediğinizi varsayarsak, yani Note.CreatedBy/ Note.LastEditByve arasında bir ilişki yoktur Person.Notes, EF'e bunu söylemeniz gerekir Note.CreatedByve Note.LastEditByiçinde karşılık gelen (aka ters) gezinme özelliğine sahip değilsiniz Person. Veri açıklamaları ile bu mümkün değildir. Bu amaç için mevcut olan tek veri ek açıklaması [InverseProperty(...)]boş / boş dize adını kabul etmez, dolayısıyla burada ihtiyaç duyulan şey için kullanılamaz.

Ayrıca burada akımı çözdükten sonra karşılaşacağınız ve veri ek açıklamalarıyla da çözülemeyen bir sorun daha var. İle arasında birden çok gerekli (dolayısıyla varsayılan olarak kademeli silme) ilişkiniz Personolduğundan Note, SqlServer ile ünlü "döngüleri veya birden çok basamaklı yollar" sorununu yaratır ve basamaklı silme işlemlerinden en az birinin kapatılmasını gerektirir.

Bununla birlikte, söz konusu modelin aşağıdaki minimum akıcı yapılandırmaya ihtiyacı vardır:

modelBuilder.Entity<Note>()
    .HasOne(e => e.CreatedBy)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Note>()
    .HasOne(e => e.LastEditBy)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict);

Orijinal sayı için esas olan HasOne/ WithManyçiftleridir. Bunu yaptıktan sonra, EF Core, eşlenmemiş Person.Noteskoleksiyonu, ters gezinme özelliği ve gölge FP özelliği (ve sütun) olmadan üçüncü bir isteğe bağlı ilişkiye otomatik olarak eşler "PersonId", yani eşdeğeri

modelBuilder.Entity<Person>()
    .HasMany(e => e.Notes)
    .WithOne()
    .HasForeignKey("PersonId");

Birden fazla basamaklı yol içeren ikinci sorunla ilgili olarak, bunun yerine Restrictbasamaklı olmayan herhangi bir seçeneği veya daha yenisini kullanabilirsiniz ClientCascade. Ve bu, ilişkilerden sadece biri için olabilir, “kademeli yolu” kırdığı anda (model tarafından talep edildiği için görünüşe göre döngüyü kıramazsınız).