使用Lambda表达式通过导航属性获取数据,LINQToEntities

3
我正在使用LINQToEntities、Entity Framework和Lambda表达式,由于我刚开始使用这些技术,所以在获取一些数据时遇到了问题。
让我解释一下我的情况:
我有一个包含4个表的数据库,如下图所示:
(图片已省略)
当我在Visual Studio(2010)中从数据库生成模型时,结果如下:
(图片已省略)
我查找了一些信息,发现由于t_user_role表仅具有其两个父表的ID,因此该表被抽象成模型,必须使用导航属性来代替它。
我在获取给定系统上用户的角色信息时遇到了一些问题(如下函数所示)。
    public t_role GetRoleForUser(string userId, string sysId)
    {
        entities = new secfinEntities(); //context from the model

        t_role userRole = entities.t_role.Where(r => r.t_user.Any(u => u.uid == userId) & r.sys_id == sysId).First();

        return userRole;
    }

现在我需要实现一个简单的搜索功能,可以查找包含提供的字符串的用户,并返回用户的id和名称(uid,user_name)以及他们在给定系统上的角色信息(role_id,role_name),所以基本上我想将这个SQL查询转换成Lambda表达式(请注意,在模型中,表t_user_role已经被抽象化了)。
SELECT U.uid, U.user_name, R.role_id, R.role_name
FROM t_user U
    INNER JOIN t_user_role UR ON U.uid = UR.uid
    INNER JOIN t_role R ON UR.role_id = R.role_id
WHERE R.sys_id = @p0 -- first parameter
    AND U.user_name LIKE '%' + @p1 + '%' -- second parameter

此外,我想将其结果存储在我定义的类型列表中:
public class UserRole
{
    public string UserId { get; set; }
    public string UserName { get; set; }
    public string RoleId { get; set; }
    public string RoleName { get; set; }

    public UserRole(string uid, string uname, string rid, string rname)
    {
        UserId = uid;
        UserName = uname;
        RoleId = rid;
        RoleName = rname;
    }
}

在解释我已经做了什么和我正在尝试做什么之后,首先的问题是:如何实现?第二个问题是:是否可以通过冗长的形式而不是Lambda表达式来完成相同的事情?如果可以,怎样实现?

非常感谢您的时间。


提供我们需要的信息,以便帮助您解决问题。如果您能够提供准确的信息,我们将会给您加一分。 - Smudge202
1个回答

4
这是一段 T-SQL 代码:
SELECT U.uid, U.user_name, R.role_id, R.role_name 
FROM t_user U 
    INNER JOIN t_user_role UR ON U.uid = UR.uid 
    INNER JOIN t_role R ON UR.role_id = R.role_id 
WHERE R.sys_id = @p0 -- first parameter 
    AND U.user_name LIKE '%' + @p1 + '%' -- second parameter 

考虑到您的模型将转换为此冗长的语法(包括使用您的新模型的要求):

var results = (from u in entities.t_user
              from r in u.t_role
              where r.sys_id == sysIdVariable && u.user_name.Contains(userNameVariable)
              select new UserRole(u.uid, u.user_name, r.role_id, r.role_name))

我知道你没有要求,但是 lambda 版本可能如下所示:

var results = entities.t_user.Join(entities.t_role, 
                                   x => x.t_role_id, 
                                   x => x.role_id, 
                                  (u, r) => new UserRole(u.uid, 
                                                         u.user_name, 
                                                         r.role_id, 
                                                         r.role_name))

现在我感到羞愧,因为它非常简单,而我最初认为只能用lambda表达式来完成...虽然这是我第一次看到像那样的2个形式,但它确切地做了什么? - Emmanuel Medina
1
在这个例子中,它是一种简写形式,用于在存在关系的导航属性时执行连接。另一种选择是(请原谅注释框中的代码...)from u in entities.t_user join r in entities.t_role on u.t_role_id == r.role_id where.... 您还可以将其用于连接_不相关_的实体,因为您可以指定不同的键来连接它们等。不过不要感到羞耻,好消息是,您的问题是我本周在该网站上看到的最好的阅读材料! :-) - Smudge202
我花了很长时间来确保我包含了可能的每一个细节,因为我不想比必要的情况下更加苦恼。感谢您的解释,我会记住这个经验的 :) - Emmanuel Medina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接