通过实体框架和Where子句通过Linq To实体进行左外连接

Eul*_*tor 4 linq-to-entities entity-framework left-join outer-join

在使用实体框架时,我已阅读了与在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;
    }
Run Code Online (Sandbox Code Playgroud)

我需要创建一个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')
Run Code Online (Sandbox Code Playgroud)

我生成的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();
    }
Run Code Online (Sandbox Code Playgroud)

任何帮助,想法或建议将不胜感激.

EulerOperator

Adu*_*cci 11

.NET 3.5

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();
Run Code Online (Sandbox Code Playgroud)

.NET 4.0

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();
Run Code Online (Sandbox Code Playgroud)