查找非多对多关系的实体



我可能会看这个错误的方式,但我有一个基本的多对多代码优先设置在EF Core 3.1与部门<->DepartmentDay & lt;→一天。

modelBuilder.Entity<DepartmentDay>(entity =>
{
entity.HasKey(dd => new { dd.DepartmentId, dd.DayId });
entity.HasOne(dp => dp.Day)
.WithMany(p => p.DepartmentDays)
.HasForeignKey(d => d.DayId);
entity.HasOne(dp => dp.Department)
.WithMany(p => p.DepartmentDays)
.HasForeignKey(d => d.DepartmentId);
});

第一个问题:这个关系是可选的吗,我可以有几天没有连接到一个部门?我需要这个,因为这与开放时间有关,并且希望有影响所有部门的通用日,而不必与所有部门建立特定的联系。但正如我在开头所说的,我可能会以错误的方式看待这件事。

第二个问题:如果问题1是正确且有效的设置,我如何在Linq-query中获得未连接到部门的天数?

到目前为止我所拥有的是(编辑:将allDays从哈希集更改为列表)

var allDays = await _context.Days.ToListAsync();
var allDepartmentDays = _context.DepartmentDays.Select(dd => dd.DayId).ToHashSet();
var genericDays = allDays.Where(d => !allDepartmentDays.Contains(d.Id));

或者在这里使用原始查询更好吗?

SELECT Id
FROM Day
WHERE Id NOT IN (SELECT DayId FROM DepartmentDay)
编辑2:包括整个数据模型
public class Department
{
public int Id { get; set; }
public int DepartmentNr { get; set; }
public string Service { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public string Postal { get; set; }
public string City { get; set; }
public string Url { get; set; }
public string MapUrl { get; set; }
public DateTime Created { get; set; }
public string CreatedBy { get; set; }
public DateTime? Updated { get; set; }
public string UpdatedBy { get; set; }
public ICollection<DepartmentPeriod> DepartmentPeriods { get; set; }
public ICollection<DepartmentDay> DepartmentDays { get; set; }
}
public class DepartmentDay
{
public int DepartmentId { get; set; }
public int DayId { get; set; }
public Department Department { get; set; }
public Day.Models.Day Day { get; set; }
}
public class Day
{
public int Id { get; set; }
public int PeriodId { get; set; }
public string Service { get; set; }
public string City { get; set; }
public DateTime? Date { get; set; }
public DayOfWeek? DayOfWeek { get; set; }
public DateTime? OpenTime { get; set; }
public DateTime? CloseTime { get; set; }
public bool IsClosed { get; set; }
public string Description { get; set; }
public DateTime Created { get; set; }
public string CreatedBy { get; set; }
public DateTime? Updated { get; set; }
public string UpdatedBy { get; set; }
public ICollection<DepartmentDay> DepartmentDays { get; set; }
public virtual Period.Models.Period Period { get; set; }
}
modelBuilder.Entity<Day>(entity =>
{
entity.HasOne(d => d.Period)
.WithMany(p => p.Days)
.HasForeignKey(d => d.PeriodId);          
});

初始问题中没有包含另一个关系,它回答了我的第一个问题,Department 1-M DepartmentPeriod M-1 Period 1-1 Day。所以Day表中会有与DepartmentDay没有关系的天数,而只与Period和两者都没有关系,对吗?

第一个问题:它是可选的吗?如果没有数据类型,这确实是一个棘手的问题,但是假设导航属性已经正确地设置好了,如果导航属性的键没有命名为{DataType}Id,那么您只需要指定导航属性,因此如果您这样命名它们,则不需要指定,否则您必须指定要使用哪些外键字段以及哪些是键。如果您不指定关系,实体框架将为您生成多对多关系的表。

第二个问题:在性能方面,SQL查询总是优于如果你能够写一个好的查询,你建议的那个,甚至

select a.id from [day] a left join departmentday b on a.id = b.dayid where b.dayid is null

即便如此,的表现也会稍好一些,然而,在可测试性方面,sql是一个问题,因为我们想要运行一个实体dbcontext的InMemory模型,然后你的sql至少不能正常执行。

所以问题是,如果你真的需要额外的性能,并且有可能编写一个linq查询,使linq引擎能够有效地编写类似的查询,通过使其成为相同表达式的一部分,而不是两个或多个。

在您的情况下,我可能在数据模型中缺少一些目前未提供的东西,但似乎您可以像这样得到您想要的:

_context.Days.Include(d => d.DepartmentDays).Where(!d.DepartmentDays.Any());

更新:看看模型,似乎有一些模型工作缺失,你正在寻找的投影可以沿着建议的路线完成。

对模型创建的更改/添加:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>()
.HasKey(k => k.Id);
modelBuilder.Entity<DepartmentDay>()
.HasKey(k => new { k.DayId, k.Department });
modelBuilder.Entity<Day>()            
.HasOne(d => d.Period)
.WithMany(p => p.Days)
.HasPrincipalKey(k => k.PeriodId)
.HasForeignKey(d => d.Id);

//Notice your departmentid is not alone a foreign key in the relationship table, as departments can have one row per day
modelBuilder.Entity<DepartmentDay>()
.HasOne(a => a.Department)
.WithMany(b => b.DepartmentDays)
.HasPrincipalKey(p => p.Id)
.HasForeignKey(f => new { f.DepartmentId, f.DayId });
base.OnModelCreating(modelBuilder);
}
在上下文中,我们可以使用 来进行这样的查询:
public List<Day> GetDaysWithoutAnyDepartmentDays()
{
return Days
.Include(i => i.DepartmentDays)
.Where(x => !x.DepartmentDays.Any()
).ToList();
}

相关内容

  • 没有找到相关文章

最新更新