[CSHARP-1348] Manual constructed expressions problem Created: 16/Jul/15  Updated: 17/Jul/15  Resolved: 17/Jul/15

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 2.0.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Daniel Slapman Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Zip Archive Yoba.zip    

 Description   

I have a simple "Event" class with a DateTime "Time" property.
Let "eventColelction" be IMongoCollection<Event>

If I create an index using the following code

Task.Run(() => eventCollection.Indexes.CreateOneAsync(Builders<Event>.IndexKeys.Ascending(_ => _.Time))).Wait();

everything works fine.

Then, I constructed expression by hand:

var arg = Expression.Parameter(typeof(Event), "arg");
            var getter = Expression.Property(arg, typeof (Event).GetProperty("Time"));
            var convert = Expression.Convert(getter, typeof(object));
            var exp2 = Expression.Lambda<Func<Event, object>>(convert, arg);
Task.Run(() => eventCollection.Indexes.CreateOneAsync(Builders<Event>.IndexKeys.Ascending(exp2))).Wait();

it worked again.

Then I ported the code to F# (it was my original goal):

let arg = Expression.Parameter(typeof<Event>, "arg")
let getter = Expression.Property(arg, typeof<Event>.GetProperty("Time"))
let convert = Expression.Convert(getter, typeof<obj>);
let exp = Expression.Lambda<Func<Event, obj>>(convert, arg);
 
let createIndex keyDefinition =
        eventCollection.Indexes.CreateOneAsync(keyDefinition) |> Async.AwaitTask |> Async.RunSynchronously |> ignore
 
createIndex (Builders<Event>.IndexKeys.Ascending(exp))

And it ended with "System.InvalidOperationException: Unable to determine the serialization information for arg => Convert(arg.Time)."

The question is why? Expression are just identical.



 Comments   
Comment by Craig Wilson [ 17/Jul/15 ]

Thanks Daniel. I'll close the ticket.

Yes, we have plans to make the F# driver a reality. It's just about finding the time amidst all our other priorities.

Craig

Comment by Daniel Slapman [ 16/Jul/15 ]

I just built Max Hirschhorn's serializers from mongo-fsharp-driver-prototype, the problem disappeared.
I'm sorry for bothering with this, I must test my homebrew serializer better.

By the way, are there any plans to continue work on official F# driver?

Comment by Daniel Slapman [ 16/Jul/15 ]

I'd attached the solution, hope it will help.

Comment by Daniel Slapman [ 16/Jul/15 ]

My main goal is to avoid "magic strings".
I have a generic "translator" from quotations to expressions:
https://github.com/leviysoft/QuotationTranslator

Comment by Daniel Slapman [ 16/Jul/15 ]

Hi Craig,
Thanks for Your fast reply! I can send a sample solution to save Your time reproducing the problem.

Comment by Craig Wilson [ 16/Jul/15 ]

Just to note... using a string instead of the expression tree will garner you the same results. When we have a typed collection, we'll attempt to match a string up to a property or field and do the translation correctly if, for instance, the property was mapped to a different field name. So, if you are using reflection to get the property name, just use the property's name and it should be handled.

let propName = typeof<Event>.GetProperty("Time").Name
 
let createIndex keyDefinition =
        eventCollection.Indexes.CreateOneAsync(keyDefinition) |> Async.AwaitTask |> Async.RunSynchronously |> ignore
 
createIndex (Builders<Event>.IndexKeys.Ascending(propName))

Comment by Craig Wilson [ 16/Jul/15 ]

Hi Daniel,

Thanks for the report. I'll have to look into it. We don't currently have any tests in F# so there is a good likelihood that some things won't work.

Craig

Generated at Wed Feb 07 21:39:20 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.