繁体   English   中英

如何在Entity Framework中加入对象

[英]How to do join with objects in Entity Framework

因此,我正在使用实体框架将具有普通SQL查询的旧项目转换为ORM。 所以我创建了这样的数据库模型:

数据库模型

所以我有这个旧的查询,我想转换为linq表达式

SELECT UGLINK.USERNAME 
FROM GMLINK 
INNER JOIN UGLINK 
ON GMLINK.GROUPID = UGLINK.GROUPID 
WHERE (((GMLINK.MODULEID)=%ID%))

我遇到的问题是我无法弄清楚如何使用对象进行连接查询。 相反,我必须通过这样的属性(似乎工作):

// So this is one of the module objects that is located in a listView in the GUI
Module m = ModuleList.selectedItem as Module;

/* Now I want to fetch all the User objects that, 
 * via a group, is connected to a certain module */
var query = context.gmLink
    .Join(context.ugLink,
          gmlink => gmlink.GroupId,
          uglink => uglink.GroupId,
          (gmlink, uglink) => new { gmLink = gmlink, ugLink = uglink })
    .Where(gmlink => gmlink.gmLink.ModuleId == m.ModuleId)
    .Select(x => x.ugLink.User);

正如我所说的那样有效,但正如你所看到的那样,我必须通过链接表属性.GroupId.ModuleId等连接模块。 相反,我想通过EF创建的对象。

我想写一个类似这样的问题,但无法弄清楚如何做到这一点,它是否可能?

var query = context.User
            .Select(u => u.ugLink
                .Select(uglink => uglink.Group.gmLink
                    .Where(gmLink => gmLink.Module == m)));

如果启用了延迟加载,则不需要应用特定的连接表示法(可以直接访问导航属性) - 但针对SQL运行的查询效率低下(通常结果会在许多不同的select语句中返回) 。

我的偏好是在上下文中禁用延迟加载,并使用.Include()表示法手动将表连接在一起,从而通常可以提高查询效率。 .Include()用于显式连接Entity Framework中的实体。

Join()具有误导性,不适合在EF中连接表。

所以,要复制这个声明:

SELECT UGLINK.USERNAME 
FROM GMLINK 
INNER JOIN UGLINK 
ON GMLINK.GROUPID = UGLINK.GROUPID 
WHERE (((GMLINK.MODULEID)=%ID%))

您将使用以下内容:

var query = context.gmLink
    .Include(x => x.Group.gmLink)
    .Where(x => x.ModuleId == myIdVariable)
    .Select(x => new {
        UserName = x.Group.ugLink.UserName
    });

假设您的导航属性已正确设置。 我没有测试过这个,所以我不是100%的语法。

在编写和运行针对数据库的LINQ to Entity查询时,您应该真正运行SQL事件探查器,这样您就可以了解实际生成的内容并针对您的数据库运行。 很多时候,EF查询可能正常运行,但在部署到生产系统时可能会遇到性能问题。

本白皮书可能会帮助您。

这应该是有效的:

var query = context.gmLink
    .Where(gmlink => gmlink.ModuleId == m.ModuleId)
    .SelectMany(gmlink => gmlink.Group.ugLink)
    .Select(uglink => uglink.User);

在EF中使用.Where(gmlink => gmlink.Module == m)过滤gmLink是不可能的,因此需要使用标识符进行比较。 另一个选项是.Where(gmlink => gmlink.Module.ModuleId == m.ModuleId)

我还没有测试过,但是这样的话:

var users = context.User
    .Where(x => x.ugLink
        .Any(y => context.gmLink
                    .Where(z => z.ModuleId == m)
                    .Select(z => z.GroupId)
                    .Contains(y.GroupId)
        )
    )
    .ToList();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM