C# 如何在实体框架中连接对象
因此,我正在使用实体框架将带有普通SQL查询的旧项目转换为ORM。因此,我创建了如下数据库模型:C# 如何在实体框架中连接对象,c#,sql,linq,entity-framework,C#,Sql,Linq,Entity Framework,因此,我正在使用实体框架将带有普通SQL查询的旧项目转换为ORM。因此,我创建了如下数据库模型: var users = context.User .Where(x => x.ugLink .Any(y => context.gmLink .Where(z => z.ModuleId == m) .Select(z => z.GroupId)
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();
所以我有一个旧的查询,我想把它转换成一个linq表达式
SELECT UGLINK.USERNAME
FROM GMLINK
INNER JOIN UGLINK
ON GMLINK.GROUPID = UGLINK.GROUPID
WHERE (((GMLINK.MODULEID)=%ID%))
我的问题是,我不知道如何使用对象进行连接查询。
相反,我必须通过这样的属性(这似乎是可行的):
正如我所说,这是可行的,但正如您所看到的,我必须通过链接表属性.GroupId
和.ModuleId
等来连接模块。相反,我想浏览EF创建的对象
我想写一个有点像这样的问题,但不知道怎么做,有可能吗
var query = context.User
.Select(u => u.ugLink
.Select(uglink => uglink.Group.gmLink
.Where(gmLink => gmLink.Module == m)));
我还没有测试过,但类似这样:
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();
如果启用了延迟加载,则不需要应用特定的连接表示法(您可以直接访问导航属性),但是针对SQL运行的查询效率很低(通常结果在许多不同的select语句中返回) 我的首选是禁用上下文上的延迟加载,并使用.Include()表示法手动将表连接在一起,从而产生通常更高效的查询。Include()用于显式连接实体框架中的实体 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 profiler,这样您就可以了解实际生成的内容并对数据库运行这些查询。很多时候,EF查询可能运行正常,但部署到生产系统时可能会遇到性能问题
可能会帮助您解决问题。这应该可以:
// 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);
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)
好的,除了m必须被m.ModuleId替换外,这是有效的,所以在某种意义上这比我的尝试更好,但是它仍然连接.ModuleId
和.GroupId
即原语而不是对象(但可能这是唯一的方法?嗯,啊,好吧,这看起来非常简洁,但我的初始表达式只得到用户名,而不是整个用户。我没有注意到。很抱歉给您带来不便,但我需要用户对象…更新为仅输出用户对象。您可以使用.Select()进行项目)插入谓词输入允许的任何形式。你说得对,对不起-当你面前没有VS时,很难准确地编写定制代码:)不幸的是,这也不起作用,因为Gourp.ugLink
是一个“ugLink”列表,而不仅仅是一个“ugLink”…Include()仍然是明确的方向。可能我的代码有误导性,因为我不完全理解您的数据结构。