在使用实体框架时,我已阅读了与在Linq to Entities(.NET 3.5)中实现等效的LEFT OUTER JOIN相关的所有帖子,但尚未找到解决以下问题的方法。
给出两个表,由下面的对象表示:
public class Foo
{
public int FooId; // primary key
public string Name;
}
public class Bar
{
public int BarId; // primary key
public int FooId; // foreign key
public string Desc;
}
我需要创建一个Linq to Entities语句,它是以下SQL语句的EQUIVALENT。请注意,WHERE语句包含两个OR'd条件,这两个条件跨越两个表,并使用DISTINCT限定符。
SELECT DISTINCT
Foo.*
FROM
Foo
LEFT OUTER JOIN Bar ON Foo.FooId = Bar.FooId
WHERE
(Foo.Name = 'fooname' OR Bar.Desc = 'bardesc')
我生成的Linq查询是通过实体框架实现Linq到实体,并且(希望)生成一个要在服务器上执行的SQL语句。 Linq to Entities不支持FirstOrDefault()扩展子句,因此LEFT OUTER JOIN的标准Linq语法将不起作用。
以下是我的解决方案,但我无法执行以下任一操作:
1)生成一个结果集,其中包含LEFT OUTER JOIN操作返回的一组Foo / Bar组合。
2)实现WHERE子句的等价物:WHERE (Foo.Name = 'fooname' OR Bar.Desc = 'bardesc')
private class JoinSet
{
public Foo Foo;
public IQueryable<Bar> Bars;
};
private class FooBar
{
public Foo Foo;
public Bar Bar;
};
IEnumerable<Foo> OuterJoinTest()
{
IQueryable<Foo> fooBaseQuery = dbContext.FooSet;
IQueryable<Bar> barBaseQuery = dbDontext.BarSet;
IQueryable<JoinSet> joinQuery =
from foo in fooBaseQuery
select new JoinSet
{
Foo = foo,
Bars = barBaseQuery.Where(bar => bar.FooId == foo.FooId)
};
// How do I generate a result set containing FooBar objects ?
// How or where do I insert the equivalent of: ?
// WHERE (Foo.Name = 'fooname' OR Bar.Description = 'bardesc')
IQueryable<Foo> resultQuery =
from joinSet in joinQuery
select joinSet.Foo;
resultQuery = resultQuery.Distinct();
return resultQuery.ToList();
}
任何帮助,想法或建议都将不胜感激。
EulerOperator
答案 0 :(得分:11)
private class FooBar
{
public Foo Foo { get; set; }
public Bar? Bar { get; set; }
}
var innerQuery = from foo in context.Foos
from bar in context.Bars
where foo.Name == 'fooname' || bar.Description == 'bardesc'
where foo.FooId == bar.FooId
select new FooBar { Foo = foo, Bar = bar };
var outerQuery = from foo in context.Foos
where foo.Name == 'fooname'
where !context.Bars.Any(b => b.FooId == foo.FooId)
select new FooBar { Foo = foo, Bar = null };
var leftouterjoinQuery = innerQuery.Union(outerQuery).Distinct();
var query = (from foo in context.Foo
join b in context.Bar
on foo.FooId equals b.FooId into Bar
from bar in Bar.DefaultIfEmpty()
where foo.Name = 'fooname' || bar.Description = 'bardesc'
select new { foo, bar }).Distinct();