首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F# FSharp.Data.SqlClient无法识别存储过程中的多个返回表

F# FSharp.Data.SqlClient无法识别存储过程中的多个返回表
EN

Stack Overflow用户
提问于 2017-01-10 13:38:11
回答 1查看 220关注 0票数 4

我不确定这是否可能,但我还没有找到这个用例的清晰文档。我正在使用F# 4和FSharp.Data.SqlClient库连接到SQL Server2016。我想调用一个返回多个表的存储过程,并将这些表转换为相应的记录。在本例中,第一个表由items组成,第二个表由customers组成。

我的直觉是它应该看起来像这样:

代码语言:javascript
复制
let items, customers = cmd.Execute()

我的直觉是items应该是一个IEnumerable<item>customers应该是一个IEnumerable<customer>,其中itemcustomer都是记录类型。实际上,FSharp.Data.SqlClient只看到了从存储过程返回的第一个表。我正在开发一个SQL Server 2016开发人员实例。下面是设置该示例的T-SQL:

代码语言:javascript
复制
create table Item (
    ItemID int identity(1, 1) primary key,
    ItemName nvarchar(50)
)
go

create table Customer (
    CustomerID int identity(1, 1) primary key,
    CustomerName nvarchar(50)
)
go

insert into Item (ItemName) values ('A');
insert into Item (ItemName) values ('B');
insert into Item (ItemName) values ('C');

insert into Customer (CustomerName) values ('Gary');
insert into Customer (CustomerName) values ('Sergei');
insert into Customer (CustomerName) values ('Elise');
go

create procedure dbo.ExampleProcedure
as
begin
    set nocount on;

    select
        ItemID,
        ItemName
    from Item

    select
        CustomerID,
        CustomerName
    from Customer

end;

这是我正在测试的F#脚本。它显示了我希望能够做的事情,但我在最后一行得到了编译错误:

代码语言:javascript
复制
#r "../packages/FSharp.Data.SqlClient.1.8.2/lib/net40/FSharp.Data.SqlClient.dll"
#r "../packages/FSharp.Data.2.3.2/lib/net40/FSharp.Data.dll"
#r "System.Xml.Linq.dll"
open FSharp.Data

[<Literal>]
let connStr = 
    "Data Source=**connection string**;"

type queryExample = SqlProgrammabilityProvider<connStr>
do
    use cmd = new queryExample.dbo.ExampleProcedure(connStr)
    let items, customers = cmd.Execute()

我希望items与第一个返回表相对应,customers与第二个返回表相对应。intellisense表明FSharp.Data.SqlClient只能看到第一个表。当我将鼠标悬停在cmd.Execute()上时,弹出窗口显示"This expression was expected to have type 'a*'b but here has type System.Collections.Generic.IEnumerable<SqlProgrammabilityProvider<...>.dbo.ExampleProcedure.Record>"。如果我执行以下操作,我就可以访问存储过程中的Items查询:

代码语言:javascript
复制
// Learn more about F# at http://fsharp.org. See the 'F# Tutorial' project
// for more guidance on F# programming.
#r "../packages/FSharp.Data.SqlClient.1.8.2/lib/net40/FSharp.Data.SqlClient.dll"
#r "../packages/FSharp.Data.2.3.2/lib/net40/FSharp.Data.dll"
#r "System.Xml.Linq.dll"
open FSharp.Data

[<Literal>]
let connStr = 
    "Data Source=**connection string**;"

type queryExample = SqlProgrammabilityProvider<connStr>
do
    use cmd = new queryExample.dbo.ExampleProcedure(connStr)
    for item in cmd.Execute() do
        printfn "%A" item.ItemID

这有可能吗?我的方法是错的吗?我找不到关于这个用例的明确文档,但我认为它将是足够常见的,它将被涵盖。

更新

为了澄清我试图实现的目标,我展示了如何在C#中解决这个问题。在C#中,我创建了一个DataSet对象,并用存储过程的结果填充它。从那里,我挑选出要使用的各个表。在提取表之后,我使用LINQ将行转换为相应的对象。它通常看起来如下所示:

代码语言:javascript
复制
using System.Data;
using System.Data.SqlClient;

var connStr = "**connection string**"
var sqlConnection = new SqlConnection(connStr );
var sqlCommand = new SqlCommand("ExampleProcedure", sqlConnection);
sqlCommand.CommandType = CommandType.StoredProcedure;
var dataSet = new DataSet();
var adapter = new SqlDataAdapter(sqlCommand);
adapter.Fill(dataSet);
var itemsTable = dataSet.Tables[0];
// Turn the itemsTable into a List<Item> using LINQ here
var customersTable = dataSet.Tables[1];
// Turn the customersTable into List<Customer> using LINQ here

我发现对于提取单个表这样简单的事情来说,这过于冗长,但可能我对代码混乱太敏感了。我知道F#一定有更优雅、更简洁的方式来表达这一点。

EN

回答 1

Stack Overflow用户

发布于 2017-05-31 02:33:20

我不知道F#,但是这是一个数据访问问题。

当一个存储过程返回多个结果集时,您需要依次访问它们。

cmd.ExecuteReader()返回一个指向第一个结果集的datareader实例。你需要处理这个结果集,可能是用一个自定义类的实例填充一个列表,然后调用"NextResult“方法,然后你就可以访问下一个结果集了,依此类推。

“NextResult”方法的引用:https://msdn.microsoft.com/pt-br/library/system.data.sqlclient.sqldatareader.nextresult(v=vs.110).aspx

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41561826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档