代码之家  ›  专栏  ›  技术社区  ›  Alex Yakunin

非常复杂的LINQ(to SQL)查询示例

  •  5
  • Alex Yakunin  · 技术社区  · 15 年前

    我们正在考虑为ormbattle.net添加更多的LINQ测试,但没有更多的想法。所有的LINQ测试都在检查常见的LINQ功能:

    • 任何测试都必须将Linq传递给IEnumerable
    • 对于任何测试,必须至少有一个ORM,它通过(实际上,无论它是否在@ormbattle中列出都无关紧要)。

    目前,LINQ测试序列的目标是 自动地 计算LINQ实现覆盖率得分。

    先决条件:

    如果您对可以添加的内容有任何想法,请与我们分享。我一定会接受的 任何 满足上述要求的LINQ查询示例,可能还有一些与测试套件改进相关的好主意,即 可以实现 (例如,如果你建议我们手动学习翻译质量,这就行不通了,因为我们无法自动完成这项工作)。

    1 回复  |  直到 15 年前
        1
  •  8
  •   Marc Gravell    15 年前
    1. Expression.Invoke 对于子表达式;用于linq to sql和linq to对象,但不用于3.5sp1中的ef(用于 IEnumerable<T> ,呼叫 .AsQueryable() 第一):

          Expression<Func<Customer, bool>> pred1 = cust=>cust.Country=="UK";
          Expression<Func<Customer, bool>> pred2 = cust=>cust.Country=="France";
          var param = Expression.Parameter(typeof(Customer), "x");
          var final = Expression.Lambda<Func<Customer, bool>>(
              Expression.OrElse(
                  Expression.Invoke(pred1, param),
                  Expression.Invoke(pred2, param)
              ), param);
          using (var ctx = new DataClasses1DataContext())
          {
              ctx.Log = Console.Out;
              int ukPlusFrance = ctx.Customers.Count(final);
          }
      

      LINQ to SQL输出示例(EF在火花中爆炸):

      SELECT COUNT(*) AS [value]
      FROM [dbo].[Customers] AS [t0]
      WHERE ([t0].[Country] = @p0) OR ([t0].[Country] = @p1)
      -- @p0: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [UK]
      -- @p1: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [France]
      
    2. 身份管理器无往返短路-即

      var obj = ctx.Single(x=>x.Id == id);
      var obj = ctx.Where(x=>x.Id == id).Single();
      

      等应 如果具有该标识的对象已具体化并存储在标识管理器中,则需要转到数据库;也适用于 First ,请 SingleOrDefault , FirstOrDefault . 请参见Linq to SQL(另请参见 here here ;您可以通过附加到 .Log );举例:

      using (var ctx = new DataClasses1DataContext())
      {
          ctx.Log = Console.Out;
          var first = ctx.Customers.First();
          string id = first.CustomerID;
          Console.WriteLine("Any more trips?");
          var firstDup = ctx.Customers.First(x=>x.CustomerID==id);
          Console.WriteLine(ReferenceEquals(first, firstDup)); // true
          Console.WriteLine("Prove still attached");
          int count = ctx.Customers.Count();
      }
      

      日志输出只显示两次行程;一次是第一次获取对象,一次是计数;它还显示物化器返回相同的对象引用:

      SELECT TOP (1) [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[
      ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t
      0].[Country], [t0].[Phone], [t0].[Fax]
      FROM [dbo].[Customers] AS [t0]
      -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.492
      6
      
      Any more trips?
      True <==== this is object reference equality, not "are there any more trips"
      Prove still attached
      SELECT COUNT(*) AS [value]
      FROM [dbo].[Customers] AS [t0]
      -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.492
      6
      
    3. UDF支持;对于同样适用于Linq to对象的简单示例:

      partial class MyDataContext {
           [Function(Name="NEWID", IsComposable=true)] 
           public Guid Random()  { return Guid.NewGuid();}
      }
      

      然后点菜 x => ctx.Random() 例如:

      using (var ctx = new DataClasses1DataContext())
      {
          ctx.Log = Console.Out;
          var anyAtRandom = (from cust in ctx.Customers
                             orderby ctx.Random()
                             select cust).First();
      }
      

      输出:

      SELECT TOP (1) [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[        ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
      FROM [dbo].[Customers] AS [t0]
      ORDER BY NEWID()
      
    4. 如果我感觉 真正地 邪恶的, recursive lambda 可能不值得支持 任何 方式…同样,4.0表达式(DLR)节点类型。