【问题标题】:How to retrieve multiple column values with same foreign key id using Linq method Syntax in C#?如何在 C# 中使用 Linq 方法语法检索具有相同外键 id 的多个列值?
【发布时间】:2020-11-01 07:11:25
【问题描述】:

这行得通:

var query = (from user in _context.Users
             join role in _context.UserRoles on user.UserID equals role.UserId
             where user.Username == username
             select role.Role).ToArray();

我如何在方法语法中做同样的事情?

//here role.Role has multiple values

var query2 = _context.Users.Join(_context.UserRoles, u=>u.UserID,ur=>ur.UserId,
                 (u,ur)=> new { ur.Role }).ToArray();

以上代码报错:

不能隐式转换 type[] 为 'string[]'

【问题讨论】:

  • (u,ur)=> ur.Role?

标签: c# linq join linq-method-syntax


【解决方案1】:

最好使用更接近 SQL 的 LINQ 查询语法,您可以轻松修改查询。无论如何,这是您的翻译:

 var query2 = _context.Users
    .Where(u => u.Username == username)
    .Join(_context.UserRoles, u => u.UserID, ur => ur.UserId, (u,ur) => ur.Role)
    .ToArray();

【讨论】:

  • 感谢您的回答。我是一个新人,正在尝试学习不同的做事方式。所以我也尝试用方法语法来做。
  • 安装 ReShaper 扩展。它可以一键将查询语法转换为方法链。
  • 哦,我不知道会再试一次,谢谢。
  • @Madhukar 请注意@Svyatoslav 所说的话,因为很多开发人员都弄错了......Better to stay with LINQ query syntax which is closer to the SQL and you can easily modify your query. dbcontext 合作
  • @Seabizkit 感谢您的建议,我一定会遵循的。
【解决方案2】:

所以你有UsersUserRoles。 Users 和 UserRoles 之间存在一对多的关系:每个 User 都有零个或多个 UserRoles;每个 UserRole 只属于一个 User,即外键 UserId 所指的 User。

您也有一个用户名,并且您希望所有用户都有这个名称,每个用户都有自己的用户角色。

注意:您并没有说 UserName 是唯一的,所以在 Where 之后您仍然有几个用户名为“Will Smith”的用户。

简答

string userName = "Will Smith";
var result = dbContext.Users
    .Where(user => user.UserName == userName)
    .Join(dbContext.UserRoles,

        user => user.Id,               // from each User take the Id
        userRole => userRole.UserId,   // from each UserRole take the foreign key

        (user, userRole) => userRole);

或者反过来:从 UserRoles 开始,只保留那些拥有 aUser 和 userName 的 UserRoles:

dbContext.UserRoles.Where (userRole => 
    dbContext.Users
        .Where(user => user.Id == userRole.UserId  // get the User of this Role
                    && user.UserName == userName)  // check the name of this User
        .Any() );

还有改进的余地

如果用户 [10] 有 20 个用户角色,那么用户 [10] 的每个用户角色都将有一个值为 10 的外键。您将传输此值 20 次。

如果有多个“Will Smith”,您将拥有一个大序列,其中所有“Will Smiths”的所有 UserRole 随机混合。

您的解决方案将导致:

UserId UserRole
10     Administator,
10     User
25     Backup
10     Backup
18     User
25     User

对用户进行分组不是更有效吗,所以你有类似的东西:

UserId    UserRoles
10        { Administator, User, Backup }
18        { User }
25        { User, Backup }
22        <no UserRoles yet>

注意:结果略有不同:您还获得了还没有角色的用户。

当您的项目具有零个或多个子项目时,例如具有学生的学校、具有订单的客户或具有用户角色的用户,请考虑使用 Queryable.GroupJoin 的重载之一。

大多数时候我使用带有参数 resultSelector 的重载。这样您就可以准确地指定您想要的属性以及格式:

var usersWithTheirUserRoles = dbContext.Users

    // keep only the users with a specific UserName
    .Where(user => user.UserName == userName)

    // fetch some properties of the remaining users and their UserRoles
    .GroupJoin(dbContext.UserRoles,

        user => user.Id,               // from each User take the Id
        userRole => userRole.UserId,   // from each UserRole take the foreign key

        // parameter resultSelector: take each user, with its zero or more userRoles
        // to make one new:
        (user, userRolesOfThisUser) => new
        {
            // Select only the user parameters that you plan to use:
            Id = user.Id,
            Address = user.Address,
            ...

            // select the zero or more user roles of this user
            UserRoles = userRolesOfThisUser.Select(userRole => new
            {
                // Select only the properties that you plan to use
                Id = userRole.Id,
                Description = userRole.Description,
                ...

                // not needed, you've already got the value:
                // UserId = userRole.UserId,
            })
            .ToList(),
        });

优点:

  • 您还可以获得尚未拥有 UserRoles 的用户(在您的原始要求中没有问题)
  • 效率:用户的每个属性只发送一次。内连接或左外连接会一遍又一遍地发送用户的相同属性
  • 效率:您只传输您真正需要的属性
  • 您可以偏离原始表格。如果你想省略 UserRoles,或者计算一些属性,比如UserRoleCount,你可以这样做。这样可以更轻松地在未来更改您的数据库表,而无需更改此查询

【讨论】:

  • 感谢先生的回复。这有很多需要注意的地方。正如你所说,我没有提到用户名是唯一的,所以有这种可能性。表用户具有不同名称的用户,因为我在代码中确保如果尝试插入相同的用户名,它会返回一条消息,说明“用户名已经存在”。 UserRole 表由单个用户名的一个或多个角色组成,用户名可能有零个或多个角色。所以我想检索单个用户名匹配“用户名”字符串的所有角色
猜你喜欢
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-28
  • 2021-10-09
  • 2022-01-15
  • 2021-03-05
  • 1970-01-01
相关资源
最近更新 更多