我正在使用f#来更新csv文件中的数据库,所以我使用Fsharp.Data
来解析它,它按预期运行良好,然后SqlProvider
来实现更新。
所以我从我的csv获得list
个项目,其中一个字段是我要更新的表的标识符。我来自c#背景,所以使用LINQ
我可以这样做:
var results = context.MyTable.Where(m => myList.Contains(m.Identifier))
这会给我我正在寻找的行。我试着这样做
query {
for m in ctx.Dbo.MyTable do
where (List.contains m.Identifier myList)
select m
}
并在运行时遇到此错误:
System.InvalidOperationException:从范围''引用的'FSharp.Data.Sql.Common.SqlEntity'类型的变量'm',但未定义
在Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation(FSharpExpr e)
在Microsoft.FSharp.Linq.QueryModule.EvalNonNestedInner(CanEliminate canElim,FSharpExpr queryProducingSequence)
在Microsoft.FSharp.Linq.QueryModule.clo@1727-1.Microsoft-FSharp-Linq-ForwardDeclarations-IQueryMethods-Execute [a,b](FSharpExpr`1 q)
at。$ FSI_0006.main @()
因错误而停止
然后尝试了以下
query {
for m in ctx.Dbo.MyTable do
for id in myList do
where (id = m.Identifier)
select m
}
并在编译时得到了这个:
myScript.fsx(291,30):错误FS0001:“字符串列表”类型与“System.Linq.IQueryable”类型不兼容
我确信这可以做到,我想知道我做错了什么
正确的方法是什么?
我认为这显然是错的是什么?
我刚跟着Aaron回答,这就是我的代码现在的样子,至少是相关部分:
let ctx = Sql.GetDataContext();
let getZipCodes (zipcodes: string list) =
query {
for zc in ctx.CleanZipCodes do
for id in zipcodes do
where (id = zc.ZipCode)
select zc
}
|> Seq.toList
现在我收到了这个错误:
System.Data.EntityCommandExecutionException:执行命令定义时发生错误。有关详细信息,请参阅内部异常--->
System.Data.SqlClient.SqlException:SQL语句的某些部分嵌套太深。重写查询或将其分解为较小的查询。 在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action'1 wrapCloseInAction)
在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)
在System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean& dataReady)
在System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
在System.Data.SqlClient.SqlDataReader.get_MetaData()
在System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString,Boolean isInternal,Boolean forDescribeParameterEncryption,Boolean shouldCacheForAlwaysEncrypted)
在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(的CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔returnStream,布尔异步,的Int32超时,任务&安培;任务,布尔asyncWrite,布尔inRetry,SqlDataReader的DS,布尔describeParameterEncryptionRequest)
在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,TaskCompletionSource'1 completion,Int32 timeout,Task& task,Boolean& usedCache,Boolean asyncWrite,Boolean inRetry)
在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method)
在System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior,String method)
在System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand,CommandBehavior behavior)---内部异常堆栈跟踪结束---
at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand,CommandBehavior behavior)
at System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute [TResultType](ObjectContext context,ObjectParameterCollection parameterValues)
在System.Data.Objects.ObjectQuery'1.GetResults(Nullable'1 forMergeOption) at System.Data.Objects.ObjectQuery'1.System.Collections.Generic.IEnumerable.GetEnumerator()
在Microsoft.FSharp.Collections.SeqModule.ToList [T](IEnumerable'1 source)
at。$ FSI_0006.main @()
答案 0 :(得分:3)
第二个示例中的错误似乎是LINQ to SQL的问题。您可以使用SQL实体类型提供程序解决它,该提供程序在内置类型提供程序中称为SqlEntityConnection
:
#r "System.Data.Entity"
#r "FSharp.Data.TypeProviders"
open Microsoft.FSharp.Data.TypeProviders
type SqlDb = SqlEntityConnection<"...">
let context = SqlDb.GetDataContext()
let myList = [...]
query {
for record in context.MyTable do
for id in myList do
where (id = record.Identifier)
select record
} |> Seq.toList