代码之家  ›  专栏  ›  技术社区  ›  blu

LINQ到SQL和自相关表

  •  3
  • blu  · 技术社区  · 14 年前

    dbml文件中有以下测试模型:

    Model http://www.freeimagehosting.net/uploads/a86582498a.gif

    对于测试用例,表中有4条记录,1条父记录,3条子记录。我们正在寻找特定记录的兄弟姐妹,包括特定记录。

    using (var db = new TestDataContext())
    {
        var query = 
            from f in db.Foos
            where f.Name == "Two"
            select f.Foo1.Foos;              // get the record's parent's children
    
        var foos = query.SelectMany(f => f); // project the EntitySet
    
        Assert.AreEqual(3, foos.Count());    // passes
    }
    

    这将使用以下SQL返回正确的项:

    SELECT     [t2].[FooId], 
               [t2].[ParentFooId], 
               [t2].[Name]
    FROM       [dbo].[Foos] AS [t0]
    INNER JOIN [dbo].[Foos] AS [t1] ON [t1].[FooId] = [t0].[ParentFooId]
    CROSS JOIN [dbo].[Foos] AS [t2]
    WHERE      ([t0].[Name] = @p0) 
    AND        ([t2].[ParentFooId] = [t1].[FooId])
    

    我们想知道交叉连接,这显然是SelectMany的结果?
    为了避免交叉连接,我们还有别的方法吗?

    3 回复  |  直到 14 年前
        1
  •  1
  •   Jacob Proffitt    14 年前

    您可以在Linq查询中堆栈from语句,这可能会对您有所帮助。

    var query = from f in db.Foos
                from f2 in f.Foos
                where f.Name == "Two"
                select f2;
    

    这就产生了。

    SELECT [t1].[FooId],
           [t1].[Name],
           [t1].[ParentFooId]
    FROM [dbo].[Foos] AS [t0], [dbo].[Foos] AS [t1]
    WHERE ([t0].[Name] = @p0) AND ([t1].[ParentFooId] = [t0].[FooId])
    
        2
  •  0
  •   Nick Craver    14 年前

    你也可以这样做:

    var query = from f in db.Foos
                where (from fo in db.Foos
                       where fo.Name == "Two"
                       select fo.ParentId).Contains(f.ParentId)
                select f;
    

    这将导致如下结果:

    SELECT     [t1].[FooId], 
               [t1].[ParentFooId], 
               [t1].[Name]
    FROM       [dbo].[Foos] AS [t1]
    WHERE      [t1].[ParentFooId] IN (SELECT [t0].[ParentFooId]
                                      FROM [dbo].[Foos] AS [t0]
                                      WHERE[t0].[Name] = @p0)
    

    可能有点不同(可能是 Exists() 取决于您的型号)…我没有配置文件窗口方便。

        3
  •  0
  •   Neil T.    14 年前

    试试这个:

    var siblings = DataContext.Foos.Where(a => a.FooID == 3)
        .Select(b => Foos.Where(b => Foos.ParentFooID == a.ParentFooID));
    
    Assert.AreEqual(3, siblings.Count());