RootsMagic хранит людей и семьи в двух таблицах. Таблица «Семьи» содержит записи для каждой семьи, членом которой является человек в качестве отца или матери (дети моделируются в еще одной таблице). Человек может быть членом ноля, одной или нескольких семей. Записи в таблице «Семьи» содержат хотя бы одного человека (
Код: Выделить всё
FatherId
Вот сокращенная схема:
Код: Выделить всё
Persons Families
--------- ----------
INT Id INT Id
INT sex INT FatherID
TEXT Name INT MotherID
Код: Выделить всё
Persons
ID sex Name
-------------
1 0 Father1
2 0 Son1
3 1 Grandmother
4 0 Grandfather
5 1 Mother1
6 1 Daughter1
7 1 Mother2
8 1 Daughter2
Families
ID FatherID MotherID
-------------------
1 4 3
2 1 5
3 1 7
- Семейство 1 моделирует семью Бабушка/Дедушка.
- Семейство 2 моделирует семью Отец1/Мать1 и
- Семья 3: вторая семья Отца1 с Матерью2
Семьи в модели Person, в которой перечислены все семьи, членом которых является человек (как отец или мать). В примере должны быть возвращены семьи 2 и 3 для человека 1 (Отец), семья 2 для человека 5 (Мать1) и семья 3 для человека 7 (Мать2).
Это Конечно, несложно получить семьи с помощью запроса типа db.Families.Where(f => f.FatherID == person.Id || f.MotherID == person.Id). Но я бы предпочел прямой доступ из модели Person.
Чтобы обойти эту проблему, я добавил отдельный _familyF (человек является участником как отец) и отдельные отношения _familyM (человек является членом как мать) с человеком через соответствующие внешние ключи FatherID и MotherID в Families. Затем я добавил несопоставленное свойство Families, которое возвращает объединение обоих списков.
Это вроде как работает, но использовать его очень неудобно. Вот соответствующий код:
Код: Выделить всё
using Microsoft.EntityFrameworkCore;
namespace dbexperiment.Models;
public partial class Family
{
public long Id { get; set; }
public long? FatherID { get; set; }
public long? MotherID { get; set; }
public virtual Person Father { get; set; }
public virtual Person Mother { get; set; }
}
public partial class Person
{
public long Id { get; set; }
public string Name { get; set; }
private ICollection _familiesF { get; set; } = new List();
private ICollection _familiesM { get; set; } = new List();
// return a union of both family collections
public ICollection Families => _familiesF.Union(_familiesM).ToList();
}
public class CTX : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)=> optionsBuilder.UseSqlite("test.db");
public DbSet Families { get; set; }
public DbSet Persons { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasOne(f => f.Father).WithMany("_familiesF").HasForeignKey(f => f.FatherID);
entity.HasOne(f => f.Mother).WithMany("_familiesM").HasForeignKey(f => f.MotherID);
});
modelBuilder.Entity(entity =>
{
entity.Ignore(e => e.Families);
});
}
}
Код: Выделить всё
private static void Main(string[] args)
{
using (var db = new CTX())
{
// var personsWithFamilies = db.Persons.Include(p=>p.Families).Where(p => p.Families.Any()); // p.Families.Any());
foreach (var person in personsWithFamilies)
{
Console.WriteLine(person.Name);
}
};
}
Ограничение: поскольку база данных создается сторонней программой, ее не следует изменять.< /п>
Подробнее здесь: https://stackoverflow.com/questions/785 ... oreign-key