5
Vote

Linq support: consider initializing NewExpression.Members for tuples

description

With the VS2008 and the May 2010 powerpack release, the following expression generates an error when passed to the query function:
 
<@ join db.Products db.Categories
    (fun p -> p.CategoryID)
    (fun c -> Nullable<_>(c.CategoryID))
    (fun p c -> (p, c))
|> Seq.sortBy (fun (p, c) -> c.CategoryName)
@>
 
As I understand it, the SQL translation does not know how to handle tuple.Item2.CategoryName unless it has type information about the members of the tuple. Attached is a diff showing a small change to linq.fs where, when handling Patterns.NewTuple, the Members member of the NewExpression is initialized by passing a third parameter to Expressions.New. With that change, I am able to execute the above query successfully.
 
My change may not be the best way to add this support, but I think the support should be added at least for tuples (and possibly for records as well).

file attachments

comments

kvb wrote Sep 15, 2010 at 6:53 AM

I think that this issue should probably be expanded to support F# records in addition to tuples, since the required changes should be quite similar.

Furthermore, this issue affects more than just joins; relatively simple queries like
<@ seq { for i in dbCtx.Table do
               if (i.Col1, i.Col2) = (1,2) then yield i } @>
are affected too. I view this as a fairly serious limitation in the current implementation.

wrote Sep 16, 2010 at 12:11 AM

wrote Oct 24, 2010 at 3:50 PM

wrote Mar 21, 2011 at 11:23 PM

wrote Feb 22, 2013 at 12:25 AM

wrote May 25, 2014 at 1:34 PM

KubuS wrote May 25, 2014 at 1:45 PM

For example the code below, used for interaction with Neo4j database, will not work since Neo4jClient library is written in C# and it needs the NewExpression.Members property to be filled out to construct the return type.
This effectively makes using F# with Neo4j very cumbersome as Tuples cannot be used for what they were designed to do i.e. to return more than one object from a function.
let results = client.Cypher
   .OptionalMatch("n-[r]-()")
   .Delete("n, r")
   .Return(fun n r -> n.CountDistinct(), r.CountDistinct()) // this brakes on the side of C# library
   .Results
   .Single()

dsyme wrote May 28, 2014 at 3:45 PM

Have you tried this in F# 3.0? The F# 2.0 LINQ power pack support got revised and added to F# 3.0 in a different form.

KubuS wrote May 28, 2014 at 11:29 PM

I work with F#3.1 in VS2013U2, NewExpression.Members is still null for Tuples - do not know about Record Types, I did not test those.

As a workaround, I extended the Neo4jClient library to manually add the missing information so now it is working as expected: https://github.com/n074v41l4bl34u/Neo4jClient/commit/3c91319380c1b5c88c55ea3307c4e8ed7bc7fe5e#diff-9077eac1c7cfb1d7fbe7732415577f5e (lines 142-158)

taylorwilson wrote May 12, 2016 at 11:31 AM

As you said you know it, the SQL translation does not know how to handle tuple. And as a programmer of Essay Writing Companies F# is new for me it will be easy to understand.