C# C Lambda左联接-无法使其工作
我正在尝试转换以下SQL:C# C Lambda左联接-无法使其工作,c#,linq,join,lambda,C#,Linq,Join,Lambda,我正在尝试转换以下SQL: select * from business left outer join permissions on permissions.permid = busid and anotherid = 17 转换为C lambda表达式,然后将其转换为可枚举项并对其执行另一个筛选。我尝试了以下代码: IEnumerable<DTO_business> business= db.business .Join(db.permis
select * from business
left outer join permissions on permissions.permid = busid
and anotherid = 17
转换为C lambda表达式,然后将其转换为可枚举项并对其执行另一个筛选。我尝试了以下代码:
IEnumerable<DTO_business> business= db.business
.Join(db.permissions,
bus => bus.busid,
perm => perm.perm_busid,
(bus, perm) => new { bus, perm })
.Where(e => e.perm.anotherid == 17).DefaultIfEmpty()
.AsEnumerable()
.Where(User.IsInRole("Administrator")
.Select(bus =>
new DTO_business()
{
BusinessID = bus.bus.busid.Convert(),
BusinessName = bus.bus.busname.Convert()
});
但我相信它不起作用,因为where在连接之外。我不确定如何在连接中实际获得该值,然后在连接上运行DefaultIfEmpty,这将为我提供左连接
编辑:我无法工作的位是:和anotherid=17。如果我把它放在一个.Where中,在linq中它会完全过滤它,而不是左连接的一部分。对于我来说,linq join子句总是简单的查询语法。如果您愿意,您可以这样做:-
var result = from permission in db.permissions
join business in db.business
on permission.permid equals business.busid into b
from bus in b.DefaultIfEmpty()
where permission.anotherid == 17
select new DTO_business()
{
BusinessID = bus != null ? bus.busid : 0,
BusinessName = bus != null ? bus.busname : String.Empty
};
imho的查询语法会更简单,但您可以使用GroupJoin这样做:
var business= db.business
.GroupJoin(
db.permissions,
bus => bus.busid,
perm => perm.perm_busid,
(bus, perm) => new { bus, perm })
.SelectMany(
z => z.permissions.DefaultIfEmpty(),
(x, y) => new { Business = x.Bus, Permission = y })
.Where(z => z.Permission.anotherid == 17)
.Select(s => new DTO_business
{
BusinessID = s.Business.busid.Convert(),
BusinessName = s.Business.busname.Convert()
});
参考:您可以在连接条件中使用复合键
from p in db.permissions
join b in db.business
on new { BusId = b.busid, AnotherId= b.anotherId}
equals new { BusId = p.perm_busid, AnotherId = 17 } into all
from b in all.DefaultIfEmpty()
select new DTO_business
{
BusinessID = b.busid, // check for null reference
BusinessName = b.busname // check for null reference
};
您也可以在扩展语法中类似地使用复合键
我在你的代码中看到你在选择函数中使用Convert。这在转换为Sql的Linq中是不允许的。感谢您的快速回答!问题是它仍然在做一个WHERE,过滤掉所有的结果。筛选器需要位于左侧外部联接上,因此如果右侧表权限未返回任何内容,则左侧表业务仍会显示。使用where-still筛选所有结果:-从逻辑上讲,如果我可以将.where放在SelectMany之上,那么它应该像筛选一样工作,这将消除权限行,但是SelectMany将返回空值。问题是上面的Where不允许我按perm进行过滤!我不确定是否可以使用查询语法,因为我需要将其转换为可枚举项。在对返回的每个项执行C非SQL函数时,在内存中获取结果。@user3129594-查询语法最终会转换为lambda并生成相同的输出。我找不到任何理由可以在这里使用查询语法。是的,但要做到这一点,我不需要创建另一个DTO,它接受来自总线和权限的所有结果,然后将iqueryable转换为ienumeral,然后在方法中进行转换吗?或者我遗漏了什么?@user3129594-不,它也会返回IEnumerable。只是尝试了一下,它仍然不起作用,因为C函数在尝试进入查询时无法运行,这是不可能的,因为它们不是基于SQL的