Linq support: consider initializing NewExpression.Members for tuples


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


kvb wrote Sep 15, 2010 at 5: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 15, 2010 at 11:11 PM

wrote Oct 24, 2010 at 2:50 PM

wrote Mar 21, 2011 at 10:23 PM

wrote Feb 21, 2013 at 11:25 PM

wrote May 25, 2014 at 12:34 PM

KubuS wrote May 25, 2014 at 12: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
   .Delete("n, r")
   .Return(fun n r -> n.CountDistinct(), r.CountDistinct()) // this brakes on the side of C# library

dsyme wrote May 28, 2014 at 2: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 10: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 10: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.