如何使用DocumentDb、LINQ和F返回多个属性?
运行下面代码的F版本时出错,而下面的C版本正常工作。一般来说,关于如何使用F从linq查询返回多个documentdb属性,您有什么想法吗如何使用DocumentDb、LINQ和F返回多个属性?,linq,f#,azure-cosmosdb,c#-to-f#,Linq,F#,Azure Cosmosdb,C# To F#,运行下面代码的F版本时出错,而下面的C版本正常工作。一般来说,关于如何使用F从linq查询返回多个documentdb属性,您有什么想法吗 2016-12-29T23:57:08.504 Exception while executing function: Functions.GetTags. mscorlib: Exception has been thrown by the target of an invocation. mscorlib: One or more errors
2016-12-29T23:57:08.504 Exception while executing function: Functions.GetTags. mscorlib: Exception has been thrown by the target of an invocation. mscorlib: One or more errors occurred. Microsoft.Azure.Documents.Client: Constructor invocation is not supported.
C
F
错误表示不支持构造函数调用。这是一个合理的限制,大多数LINQ提供商都有 在F代码中,构造函数调用是记录创建。F记录被编译为类,这些类具有一组只读属性和一个构造函数,该构造函数将这些属性的值作为参数。根据错误消息,不支持调用此构造函数。运气不好 值得注意的一件有趣的事情是,C代码中使用的C匿名类型的工作方式与F记录完全相同—它们是具有一组只读属性和一个构造函数的类—然而,它们是受支持的。作为特例处理C匿名类型也是LINQ提供者的常见做法。许多LINQ提供程序将以一种更通用的方式处理它,这也将涵盖F记录,但在本例中,情况显然并非如此。如果我是你,我会就此提出一个问题 您可以尝试将记录替换为具有可变属性的类,并使用属性初始化语法构造它:
type UserTagRecord() =
member val topics : string list = [] with get, set
member val education : string list = [] with get, set
let userTagsQuery =
user
.Where(fun user -> user.topics <> null && user.education <> null)
.Select(fun user -> UserTagRecord( topics=user.topics :?> string list, education=user.education :?> string list ) )
我还想在这里指出一个问题,即使用F列表可能会有进一步的麻烦。首先,DocumentDb可能不喜欢它们本身,其次,我不知道user.topics和user.education是什么,但我非常确定它们不是字符串列表的子类,因此您的强制转换可能会失败。感谢Fyodor的回复,它提供了有关F记录的信息,并有助于解决问题。我用[]属性注释了我的用户类,因为topic和education属性可以为null。我将这些属性初始化为null。这允许我根据user.topics null和user.education null进行筛选,因为字符串列表不支持null。然后我从obj向下转换到字符串列表。使用仅包含主题的简化UserTagRecord实现您的解决方案,并删除Where子句及其关联的强制转换要求我在执行function:Functions.GetTags时收到一个新的不同错误2016-12-30T01:46:11.710异常。mscorlib:调用的目标已引发异常。FSharp.Core:无法将以下F引号转换为LINQ表达式树----顺序值,属性设置一些returnVal,主题,[属性设置一些用户,主题,[],returnVal让我澄清一下[]属性用于避免此错误。当使用Where子句well时,类型“string list”没有将“null”作为正确的值,显然属性初始化语法无法转换为C表达式。你真不走运。我还没有用documentDB做过任何事情,但也许dynamic可以帮你一点忙?FSharp.Interop.Dynamic和System.Linq.Dynamic。再说一次,也许不是。。。
type UserTagRecord = {topics : string list; education : string list}
let userTagsQuery =
user.Where(fun user -> user.topics <> null && user.education <> null)
.Select(fun user -> {topics=user.topics :?> string list; education=user.education :?> string list})
type UserTagRecord() =
member val topics : string list = [] with get, set
member val education : string list = [] with get, set
let userTagsQuery =
user
.Where(fun user -> user.topics <> null && user.education <> null)
.Select(fun user -> UserTagRecord( topics=user.topics :?> string list, education=user.education :?> string list ) )