从数据库中选择多个列

时间:2019-02-19 08:10:33

标签: c# sql-server entity-framework

我想从数据库中选择三列(用户名,浏览器和浏览器版本),但是当我使用第一个变量时,每个用户得到多个结果。我只希望每个用户使用他使用的浏览器一次。使用第二个变量,我只获得一次用户,但没有浏览器。

var browserUser = db.Tracking.Include(t => t.Users).ToList();
var browserUserFiltered = browserUser.GroupBy(x => x.userIdFk).Select(g => g.First());


实际输出的屏幕截图
数据库模型

3 个答案:

答案 0 :(得分:1)

尝试通过FirstOrDefault选择浏览器和browserVersion:

var browserUserFiltered = browserUser.GroupBy(x => x.userIdFk).Select(g => new { 
username= g.FirstOrDefault().username,
browser= g.FirstOrDefault().browser,
browserVersion= g.FirstOrDefault().browserVersion,
});

答案 1 :(得分:1)

因此,您有UsersTrackings的序列。每个User都具有零个或多个Trackings,每个Tracking都使用外键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

问题:为什么您认为结果中只有一项?


一对多,您可以采用两种方式:

  • 获取用户的跟踪信息,这意味着在内部完成了组联接。每个用户仅一次转移到您的流程中。没有跟踪数据的用户也会出现在您的结果中。
  • 获取跟踪,每个跟踪都有其用户。内部完成内部联接。如果一个用户有多个跟踪,则同一用户数据将被发送多次。完全没有提及没有任何跟踪数据的用户。

由您决定自己想要什么。

使用“选择”代替“包含”

数据库查询的较慢部分之一是将所选数据传输到您的流程。因此,限制所选数据量是明智的。

如果用户4具有1000个跟踪,那么每个跟踪将具有一个外键UserId,其值等于4。如果您使用Include选择数据,则相同的外键值将被发送1000次,而您已经知道它等于用户主键的值:4.太浪费了!

  

查询数据时,请始终使用“选择”并仅选择您实际计划使用的属性。仅在计划更新包含的项目时才使用“包含”。

因此,要通过(某些)跟踪获取某些用户,请执行以下查询:

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(),
    });

答案 2 :(得分:0)

从npm安装morelinq,然后使用users.DistinctBy(u=>userId).ToList()

https://www.nuget.org/packages/morelinq/