EF Core 3.1.7 Tablodaki birden çok 1: 1 ilişki için veri ek açıklamaları
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
Soru şudur (ve EF'in ilişkileri otomatik olarak belirlemesini imkansız kılan şey budur) Person.Notes
ve Note.CreatedBy
/ Note.LastEditBy
- muhtemelen hiçbiri arasındaki ilişki nedir? M arasındaki ilişki: Sen 0 olduğunu söyledim Person
ve 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.LastEditBy
ve arasında bir ilişki yoktur Person.Notes
, EF'e bunu söylemeniz gerekir Note.CreatedBy
ve Note.LastEditBy
iç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 Person
olduğ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.Notes
koleksiyonu, 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 Restrict
basamaklı 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).