5

We're thinking about adding more LINQ tests for ORMBattle.NET, but have no more ideas. All LINQ tests there are checking common LINQ functionality:

  • Any test must pass on LINQ to IEnumerable
  • For any test, there must be at least one ORM, on it passes (actually it doesn't matter if it is listed @ ORMBattle or not).

Currently the goal of LINQ test sequence is to automatically compute LINQ implementation coverage score.

Prerequisites:

If you have any ideas on what can be added there, please share them. I'll definitely accept any example of LINQ query that satisfies above requirements, and possibly - some good idea related to improvement of test suite, that can be implemented (so e.g. if you'd suggest us to manually study the quality of translation, this won't work, because we can't automate this).

5
  • "Tests for support of exotic types and methods can be rejected. "Exotic" means it will be recognized as exotic by majority of ORM vendors @ ORMBattle.NET Development Google Group." Then ask the majority who has the right to approve tests to create the tests. They can basically reject anything they like by recognizing it as "exotic." Commented Dec 8, 2009 at 21:57
  • 7
    Is the question "contribute some stuff to my project?" This doesn't seem to be the proper forum for that. Commented Dec 8, 2009 at 21:58
  • Ok, to clear this up: if you'd use e.g. Uri type in your test, there is a huge chance it will be recognized as exotic - simply because there is no similar type in relational scope, but the other hand, most likely it's possible to simulate some of its method using string operations. Commented Dec 8, 2009 at 22:02
  • On the other hand, I hardly believe type like Uri will be supported by at least one ORM or LINQ provider in next few years. Ok, I'll remove condition 3 - 1 & 2 define the scope well enough. Commented Dec 8, 2009 at 22:04
  • > Is the question "contribute some stuff to my project?" Yes, partially - i.e. you must know pretty exotic context to answer it. But the question is related to coding, requires expert knowledge and likely, can be answered in just few LOC. So I was not fully sure and decided to try this. Commented Dec 8, 2009 at 22:08

1 Answer 1

8
+350
  1. Expression.Invoke for subexpressions; works on LINQ-to-SQL and LINQ-to-Objects, but not EF in 3.5SP1 (for IEnumerable<T>, call .AsQueryable() first):

        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);
        }
    

    example LINQ-to-SQL output (EF explodes in sparks):

    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. identity-manager short-circuit without roundtrip - i.e.

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

    etc should not need to go to the database if an object with that identity has already been materialized and stored in the identity-manager; applies also to First, SingleOrDefault, FirstOrDefault. See LINQ-to-SQL (also here and here; you can verify by attaching to .Log); example:

    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();
    }
    

    log output shows only only two trips; one to get the object the first time, and one for the count; it also shows the same object reference is returned by the materializer:

    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 support; for a simple example that also works for LINQ-to-Objects:

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

    and then order by x => ctx.Random(); example:

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

    with output:

    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. If I was feeling truly evil, recursive lambda; probably not worth supporting this in any way... likewise, 4.0 expression (DLR) node-types.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot! We'll definitely add 1 & 3 to tests. 2 seems pretty subjective (e.g. we decided to not spend any time on this) + implies SQL query detection (currently tests don't pay attention to SQL), so I'll ask the others. 4 is, likely, not supported by anyone, since this must imply ~ UDF generation. So let's leave this until some leave proof ;) And I agree, 4 is interesting mainly as a tricky case. But may be we'll add a test for successful detection of recursive lambda.
P.S. Marc, you're a real expert :) I hardly expected to get something new here (I thinking mainly about something like specific VB.NET methods), but case 1 was absolutely new for me. I'll ask the guys from our team - may be they knew about this. Although this seems improbable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.