gpt4 book ai didi

c# - 在多对多关系上隐藏连接实体

转载 作者:太空宇宙 更新时间:2023-11-03 12:18:16 24 4
gpt4 key购买 nike

由于 EFCore 要求您显式创建连接实体,因此我正在尝试寻找使此代码更易于管理的方法。我正在学习本教程(4 部分系列,本部分和下一部分是相关部分):https://blog.oneunicorn.com/2017/09/25/many-to-many-relationships-in-ef-core-2-0-part-2-hiding-as-ienumerable/

它将连接类作为私有(private) ICollection 隐藏起来,然后使用连接的实体填充另一个 ICollection,因此它的工作方式与 EF6 类似。这是我跟踪人们拥有的汽车的实现:

public class Person
{
public Person() =>
Cars = new JoinCollectionFacade<Car, PersonCar>
(PersonCars, pc => pc.Car, c => new PersonCar { Person = this, Car = c });

public int Id { get; set; }
public string Name { get; set; }

private ICollection<PersonCar> PersonCars { get; } = new List<PersonCar>();

[NotMapped]
public ICollection<Car> Cars { get; }
}

public class Car
{
public Car() => Persons = new JoinCollectionFacade<Person, PersonCar>
(PersonCars, pc => pc.Person, p => new PersonCar { Person = p, Car = this });

public int Id { get; set; }
public string Manufacturer { get; set; }

private ICollection<PersonCar> PersonCars { get; } = new List<PersonCar>();

[NotMapped]
public ICollection<Person> Persons { get; }
}

public class PersonCar
{
public Person Person { get; set; }
public int PersonId { get; set; }
public Car Car { get; set; }
public int CarId { get; set; }
}

我的映射:

modelBuilder.Entity<PersonCar>(e => 
{
e.HasKey(t => new { t.PersonId, t.CarId });
e.HasOne(pc => pc.Person).WithMany("PersonCars");
e.HasOne(pc => pc.Car).WithMany("PersonCars");
});

还有一些种子数据:

using (var db = new ManyDbContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();

db.Persons.AddRange(
new Person() { Name = "John" },
new Person() { Name = "Peter" },
new Person() { Name = "Paul" }
);

db.Cars.AddRange(
new Car() { Manufacturer = "Audi" },
new Car() { Manufacturer = "Honda" },
new Car() { Manufacturer = "Mercedes" },
new Car() { Manufacturer = "Ferrai" },
new Car() { Manufacturer = "Porche" }
);

db.SaveChanges();

db.PersonCars.AddRange(
new PersonCar() { PersonId = 1, CarId = 2},
new PersonCar() { PersonId = 1, CarId = 3 },
new PersonCar() { PersonId = 2, CarId = 2 },
new PersonCar() { PersonId = 3, CarId = 1 }
);

db.SaveChanges();
}

如果我拉回包括汽车在内的人员列表,如下所示,它会工作并输出数据:

var drivers = db.Persons.Include("PersonCars.Car").ToList();
foreach(var person in drivers)
{
foreach(var car in person.Cars)
{
Console.WriteLine($"{person.Name} has a {car.Manufacturer}");
}
}

但是,如果我尝试在调试器中查看 Cars 集合结果,然后 VS2017 崩溃,这不是很好,但在代码级别它似乎工作。

但是,假设我想过滤列表以仅包含 Audi 司机,以下结果为 0 个结果:

var audiDrivers = db.Persons.Include("PersonCars.Car").Where(x => x.Cars.Any(c => c.Manufacturer == "Audi"));

该系列文章主要着重于改进添加/删除,并未提及过滤。我想要该功能,但我希望能够按 Cars 过滤 Persons

如果我将 PersonCars 集合公开,那么我可以:

var audiDrivers = db.Persons
.Include(i => i.PersonCars).ThenInclude(i => i.Car)
.Where(x => x.PersonCars.Select(pc => pc.Car).Any(c => c.Manufacturer == "Audi"))
.ToList();

总结一下:

如果导航属性像文章建议的那样是私有(private)的,是否可以过滤查找?

为什么 VS2017 在查看 Car 集合时崩溃?

有没有像 EF6 一样简单的更好的方法来做到这一点?

最佳答案

我个人会直接与加入实体合作。它可能不是“漂亮”,但它是最直接的方法。最终,开发和维护代码会更容易、更快速。事实上,您在开发的早期就使用替代方法解决了这些基本问题,我认为这证明了这一点。

我的建议是:使用 EF Core,而不是反对它。它不如 EF6 成熟,但它最终会到达那里。

关于c# - 在多对多关系上隐藏连接实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48767003/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com