我有一个实体关系图如下。
ClassEntity
:
public int id
public int std
public virtual ICollection<StudentEntity> students
StudentEntity
:
public int id
public string name
public string gender
public virtual ClassEntity class
public virtual StudentAddressEntity studentAddress
StudentAddressEntity
:
public int id
public string address
我需要上课和男孩。
var classEntity = dbContext.Set<ClassEntity>().Where(t => t.id == classId);
var query = classEntity.Include(c => c.students.Select(s => s.studentAddress))
.FirstOrDefault(c => c.students.Any(s => s.gender == GenderEnum.Male));
但它正在和所有学生一起回归课堂。如何过滤男生?
答案 0 :(得分:3)
我过去使用过连接来完成类似的结果。例如,我的帐户有嵌套地址(1:M)。如果我想获得属于特定国家/地区的所有帐户,我会使用以下连接:
(from a in accountRepo.GetAll()
join aa in accountAddressRepo.GetAll() on a.AccountId equals aa.AccountId
join ad in addressRepo.GetAll() on aa.AddressId equals ad.AddressId
where ad.CountryId == codeCountryId
select a).ToList();
如果您没有使用存储库模式,则可以使用DbContext.Set()替换accountRepo.GetAll()。
在您的情况下,您应该能够加入学生,地址和班级实体,并获得类似的结果。下面的内容对您有用:
(from s in DbContext.Set<StudentEntity>
join a in DbContext.Set<StudentAddressEntity> on s.studentAddress.id equals a.id
join c in DbContext.Set<ClassEntity> on s.class.id equals c.id
where c.std == classId && s.gender== GenderEnum.Male
select s).ToList();
请注意,这是基于我对您的数据库和实体名称的理解的简单表示。您可能需要稍微调整此查询以使其可编译,但基本的想法应该适合您。请告诉我它是如何为你工作的。
答案 1 :(得分:2)
下面应该只为每个班级加载男生。
var classEntity = testContext.Set<ClassEntity>().Where(t => t.Id == classId);
var classes = classEntity.ToList().Select(c =>
{
testContext.Entry(c)
.Collection(p => p.Students)
.Query()
.Where(s => s.Gender == GenderEnum.Male)
.Load();
return c;
});
答案 2 :(得分:2)
您有意“不能”直接使用EF代理执行此操作。例如,考虑当您尝试拨打SaveChanges()
并且ClassEntity.Students
中缺少所有女学生时会发生什么!
相反,如果您只是显示数据,通常要做的是投射到匿名类型或DTO,例如: -
var classOnlyMale = dbContext.Set<ClassEntity>()
.Where(x => x.Id == classId)
.Select(x => new // I'm using an anonymous type here, but you can (and usually should!) project onto a DTO instead
{
// It's usually best to only get the data you actually need!
Id = x.Id
Students = x.Students
.Where(y => y.Gender == GenderEnum.Male)
.Select(y => new { Name = y.Name, ... })
});
或者,如果您迫切需要进行更改并保存它们: -
var classOnlyMale = dbContext.Set<ClassEntity>()
.Where(x => x.Id == classId)
.Select(x => new
{
Class = x,
MaleStudents = x.Students.Where(y => y.Gender == GenderEnum.Male)
});
除非没有办法,否则我强烈推荐前者。如果您对过滤后的数据进行更改并尝试保存,则很容易引入错误。
答案 3 :(得分:0)
根据Manish Kumar的建议,我认为加入是正确的方式。
(from s in DbContext.Set<StudentEntity>
join a in DbContext.Set<StudentAddressEntity> on s.studentAddress.id equals a.id
join c in DbContext.Set<ClassEntity> on s.class.id equals c.id
where c.std == classId && s.gender== GenderEnum.Male
select s).ToList();