我很难理解如何在我的 ASP.NET Web API v2 项目中使用 Entity Framework 6 和 SQL Server 构建我的 SQL 查询。
我的表结构:Computers
表是我的软件已清点的所有计算机的根表。它包含被其他表用作外键的列 ComputerID
。
我可以使用以下查询检索一台计算机,包括我拥有的所有信息:
Computer computer = ComputersDbContext.Computers
... more includes....
.Include("Computer_Win_Installed_Software")
... more includes....
.Where(a => a.ComputerId == computerId)
.First(t => t.TenantId == tenantId);
如您所见,我有另一个名为 Computer_Win_Installed_Software
的表,它存储了系统上安装的所有软件。它看起来像这样:
IdentityKey | ComputerID (FK) | Softwarename | EntryTimestamp
------------+-----------------+------------------+--------------
1 | 1 | Some Software | 1547241345
2 | 1 | Another Software | 1547241345
EntryTimestamp
是一个 Unix 时间戳,它对每次 list 运行都是唯一的,并且对于在该运行中发现的所有软件都是相同的。现在,如果系统再次清点,表格将如下所示:
IdentityKey | ComputerID (FK) | Softwarename | EntryTimestamp
------------+-----------------+--------------------+---------------
1 | 1 | Some Software | 1547241345
2 | 1 | Another Software | 1547241345
3 | 1 | Some Software | 1886454564
4 | 1 | Another Software | 1886454564
5 | 1 | Even More Software | 1886454564
我想保留历史数据,所以我需要保留旧条目。
我的问题是我上面的 EF 查询将在结果对象中返回所有这些条目。
如何更改我的查询以便它只返回:
IdentityKey | ComputerID (FK) | Softwarename | EntryTimestamp
------------+-----------------+--------------------+---------------
3 | 1 | Some Software | 1886454564
4 | 1 | Another Software | 1886454564
5 | 1 | Even More Software | 1886454564
我考虑过使用 2 个查询:
- 第一个查询:我检查
EntryTimestamp
的最大值 第二个查询:像这样:
Computer computer = ComputersDbContext.Computers .Include("Computer_Win_Installed_Software") .Where(a => a.ComputerId == computerId) .Where(b => b.Computer_Win_Installed_Software.EntryTimestamp == EntryTimestamp) .First(t => t.TenantId == tenantId);
但 Intellisense 立即对我尖叫 :D
我也想过只选择 MAX()
列的 EntryTimestamp
;但我什至不能在查询代码中使用 b.Computer_Win_Installed_Software.EntryTimestamp
。
当我写: .Where(b => b.Computer_Win_Installed_Software
时,它不会将任何列列为可用选项。
我认为这是因为 EF 中的 Computer_Win_Installed_Software
类是 ICollection<Computer_Win_Installed_Software>
类型。与 Computers
表都具有一对多关系的其他表也存在同样的问题。
另一个表与 Computers
表具有 1 对 1 的关系,我可以在那里选择所有列。
我 super 困惑。
是的,我搜索了谷歌,但找不到任何帮助我的东西。去这里的正确方法是什么?
编辑:添加模型
数据库上下文:
public class DbEntities : DbContext
{
public virtual DbSet<Agent> Agents { get; set; }
public virtual DbSet<Computer_Win_Installed_Software> ComputerWinInstalledSoftware { get; set; }
public DbSet<Computer> Computers { get; set; }
}
计算机的 EF 模型:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ProjectName
{
using System;
using System.Collections.Generic;
public partial class Computer
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Computer()
{
this.Computer_Win_Installed_Software = new HashSet<Computer_Win_Installed_Software>();
}
public int ComputerId { get; set; }
public int TenantId { get; set; }
public virtual Agent Agent { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Computer_Win_Installed_Software> Computer_Win_Installed_Software { get; set; }
}
}
Computer_Win_Installed_Software 的 EF 模型:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace KysoWebApi
{
using System;
using System.Collections.Generic;
public partial class Computer_Win_Installed_Software
{
public int ComputerId { get; set; }
public string SoftwareName { get; set; }
public Nullable<double> SoftwareVersion { get; set; }
public Nullable<bool> IsServerSoftware { get; set; }
public Nullable<int> SoftwareVendorId { get; set; }
public string SoftwareIs32or64bits { get; set; }
public int ComputerWinInstalledSoftwareEntryId { get; set; }
public string EntryTimestamp { get; set; }
public virtual Computer Computer { get; set; }
}
}
最佳答案
因此,对于给定的 Computer
, ICollection<Computer_Win_Installed_Software> Computer_Win_Installed_Software
总是会包含所有相关行与所有 EntryTimestampts
.你不能(轻松地)filter包括的实体。
因此,相反,只返回过滤后的实体:
var computer = ComputersDbContext.Computers
.Where(a => a.ComputerId == computerId)
.First(t => t.TenantId == tenantId);
var cwis = computer
.Computer_Win_Installed_Software
.Where(b => b.EntryTimestamp == EntryTimestamp);
当然,我不确定这是你真正想做的,你可能有一个 XY Problem .
您能否尝试不包括相关对象,而仅针对它们进行查询?
var computer = ComputersDbContext.Computers
.Where(a => a.ComputerId == computerId)
.First(t => t.TenantId == tenantId);
.Where(b => b.Computer_Win_Installed_Software.EntryTimestamp == EntryTimestamp);
关于c# - 如何选择列的最大值并检索多个结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52936354/