c# - 从数据库中选择多个列
问题描述
我想从数据库中选择三列(用户名、浏览器和浏览器版本),但是当我使用第一个变量时,我会为每个用户获得多个结果。我只希望每个用户使用他使用的浏览器一次。使用第二个变量,我获得了一次用户,但没有浏览器。
var browserUser = db.Tracking.Include(t => t.Users).ToList();
var browserUserFiltered = browserUser.GroupBy(x => x.userIdFk).Select(g => g.First());
实际输出截图
数据库模型
解决方案
所以你有Users
和的序列Trackings
。everyUser
有零个或多个Trackings
,everyTracking
完全属于一个User
,使用外键UserIdFk
。直接的一对多关系。
User Tracking
Id | Name Id | UserIdFk | <other properties>
1 | Jan 10 | 1 | A
2 | Piert 11 | 1 | B
12 | 2 | C
var browserUser = db.Tracking.Include(t => t.Users).ToList();
结果:一系列 3 个跟踪,每个跟踪都有他们的用户
Tracking: Id = 10, UserIdFk = 1; User: Id = 1; Name = Jan
Tracking: Id = 11, UserIdFk = 1; User: Id = 1; Name = Jan
Tracking: Id = 12, UserIdFk = 2; User: Id = 2, Name = Piert
进行分组:
var browserUserFiltered = browserUser.GroupBy(x => x.userIdFk)
结果:2个IGrouping的序列
Group Key: 1; Elements:
Tracking: Id = 10, UserIdFk = 1; User: Id = 1; Name = Jan
Tracking: Id = 11, UserIdFk = 1; User: Id = 1; Name = Jan
Group Key: 2; Elements:
Tracking: Id = 12, UserIdFk = 2; User: Id = 2, Name = Piert
在 GroupBy 之后继续:
.Select(g => g.First());
结果:两个项目的序列,每组一个项目:
Tracking: Id = 10, UserIdFk = 1; User: Id = 1; Name = Jan
Tracking: Id = 12, UserIdFk = 2; User: Id = 2, Name = Piert
问题:为什么您认为结果中只有一项?
在一对多中,您可以采用两种方式:
- 获取用户的跟踪信息,这意味着在内部完成了 Group-Join。每个用户只被转移到您的流程一次。没有跟踪数据的用户也在您的结果中。
- 获取跟踪,每个都有其用户。在内部完成了内部连接。如果一个用户有多个 Tracking,相同的用户数据会被发送不止一次。根本没有提到没有任何跟踪数据的用户。
由你决定你想要什么。
使用 Select 而不是 Include
数据库查询中较慢的部分之一是将所选数据传输到您的进程。因此,明智的做法是限制所选数据的数量。
如果用户 4 有 1000 个 Tracking,那么每个 Tracking 都会有一个外键 UserId,其值等于 4。如果您使用 Include 选择数据,则相同的外键值将被发送 1000 次,而您已经知道它等于用户主键的值:4。真是浪费!
查询数据时,始终使用 Select 并仅选择您实际计划使用的属性。仅当您计划更新包含的项目时才使用 Include。
因此,要获取一些带有(某些)跟踪的用户,请执行以下查询:
var result = dbContext.Users
.Where(user => ...) // only if you don't want all Users
.Select(user => new
{
// Select only the User data you actually plan to use
Id = user.Id,
Name = user.Name,
...
Trackings = user.Trackings
.Where(tracking => tracking.Date >= startDate) // only if you don't want all Trackings
.Select(tracking => new
{
// again: select only the properties you plan to use
Id = tracking.Id,
Name = tracking.Name,
...
// not needed, you know the value: UserId = tracking.UserId
})
.ToList(),
});
推荐阅读
- java - Java在导入maven包时给出NoClassDefFoundError
- tensorflow - 如何使用 ragged-tensor 在 tensorflow2 中实现以下循环代码?
- oracle - Oracle 存储过程 SQL 查询分配给变量
- install4j - 删除 install4j 中的消息
- python - 如何计算每年每个季节的季节性平均气温?
- c# - 如何在 DataGridView 中显示名称而不是 id?
- linux - 如何设置赛普拉斯在特定时间自动运行测试?
- react-native - 使用 WSL2 时可以使用 LAN 选项将手机连接到 Expo 项目吗?
- css - 当我打开 modal-lg 时背景向左移动
- graph - 如何从 amzscout 扩展图表或图表中的交互式可点击图表下载或抓取数据?