当我遇到这些问题时,我做的第一件事就是创建一个示例数据库。下面的代码创建以下内容。
1 - 数据库名为[测试]
2 - 表名为[讨论]
3 - 表名为[CategoryMap]
4 - 用户定义的表类型名为[CategoryIdArray]
5-装载带有100条记录的数据的表格
--
-- Create a test db
--
USE [master];
go
CREATE DATABASE [Test];
GO
--
-- Create the user defined type
--
USE [Test];
go
CREATE TYPE [CategoryIdArray] AS
TABLE
(
[CategoryId] [bigint] NULL
);
--
-- Create skelton tables
--
create table Discussions
(
dis_id int identity (1,1),
dis_name varchar(64),
dis_added_dte datetime default getdate()
);
go
create table CategoryMap
(
cat_id int identity(1,1),
cat_topic_id int,
cat_topic_type char(1)
);
go
-- clear tables
truncate table Discussions;
truncate table CategoryMap;
go
--
-- Create 100 rows of dummy data
--
declare @cnt int = 0;
while @cnt < 100
begin
insert into Discussions (dis_name)
values ('sample discussion record # ' + str(@cnt, 2, 0));
insert into CategoryMap (cat_topic_id, cat_topic_type)
values (@cnt+1, '1')
set @cnt = @cnt + 1;
end;
go
--
-- Show the sample data
--
select * from Discussions;
go
select * from CategoryMap;
go
第二步是重新编写存储过程。如果您在2012年以下使用,请使用窗口函数rownumber()。在2012年,订单的偏移和获取子句包含在分页中。
http://technet.microsoft.com/en-us/library/ms188385(v=sql.110).aspx
--
-- Create my procedure
--
create procedure [GetArticlesByPage]
@Tvp as [CategoryIdArray] READONLY,
@PageIndex INT = 1,
@PageSize INT = 10,
@PageCount INT OUTPUT
AS
BEGIN
-- Declare variables
DECLARE @var_recs int = 0;
DECLARE @var_offset int = 0;
-- Do not count the records
SET NOCOUNT ON;
-- Start of paging
SET @var_offset = @var_offset + ((@PageIndex - 1) * @PageSize);
-- Set page count variable
SELECT @var_recs = count(*)
FROM
[dbo].[Discussions] as d
JOIN
[dbo].[CategoryMap] as c
ON
d.dis_id = c.cat_topic_id
JOIN
@TVP a
ON
c.cat_id = a.CategoryId
WHERE
cat_topic_type = '1';
set @PageCount = ceiling(cast(@var_recs as real)/cast(@PageSize as real));
--
-- Return the record set
--
SELECT
dis_id
FROM
[dbo].[Discussions] as d
JOIN
[dbo].[CategoryMap] as c
ON
d.dis_id = c.cat_topic_id
JOIN
@TVP a
ON
c.cat_id = a.CategoryId
WHERE
cat_topic_type = '1'
ORDER BY
dis_added_dte
OFFSET @var_offset ROWS
FETCH NEXT @PageSize ROWS ONLY;
END;
GO
我没有留在原地的页数;但是,我不认为这是必要的,因为您可以重复呼叫,直到结果集为空。
请不要设置转储到一个临时表中的记录,因为它可能是相当大的,如果你是返回所有要显示的列。我选择了两个独立的电话。一个总数。一个用于单个页面。
最后一个TSQL部分是从SSMS测试存储过程。
--
-- Call the stored procedure
--
-- instantiate tvp
DECLARE @my_tvp as [CategoryIdArray];
DECLARE @my_page_cnt as int;
-- add 25 entries
declare @cnt int = 25;
while @cnt < 50
begin
insert into @my_tvp (CategoryId)
values (@cnt + 1);
set @cnt = @cnt + 1;
end;
-- show the data in the tvp
select * from @my_tvp
-- call the function
exec [GetArticlesByPage] @my_tvp, 1, 10, @PageCount = @my_page_cnt OUTPUT;
-- show the data in the output
select @my_page_cnt as 'my_pages';
go
在我的测试示例中,我想将行26到50分页为10行。结果1是25行,结果2是被分页的10行,结果3是多少页。因此,解决方案的TSQL部分是完善的。
请继续关注今晚稍后C#程序调试会话。
http://www.mssqltips.com/sqlservertip/2112/table-value-parameters-in-sql-server-2008-and-net-c/
看看这篇文章。它正在做你正在做的事情。
这里有一些想法去尝试。
1 - 确保连接属性,登录的默认数据库[测试]我的例子。
2是在[Test]数据库中定义的类型吗?请仔细检查一下。
3 - 这是正确的吗?列名称是数据库类型中的[CategoryId]。你有以下 - [类别]。尝试更改C#代码中的名称。
dt_Categories.Columns.Add( “类别” 的typeof(字符串));
4 - 删除[dbo]。来自SP中的类型。它不在MS SQL Tips的示例中。可能会混淆这个问题。 SQL服务器将解析名称。
5 - 我注意到类型被定义为大INT但表中的ID为int?确保数据类型一致。
请尝试这些建议。回到我身上,看看你是怎么做出来的。
如果这仍然是一个问题,你能否给我一个详细的调用堆栈跟踪和错误消息?
因此,这里是我答应了C#控制台应用程序。
它按预期工作。
你在混合一些构思ADO.NET和数据表的基础。你应该习惯看直接窗口和局部变量。这将帮助您追踪问题。
这是我对存储过程的示例调用。
1 - 设置数据表(50到74)
2 - 页面由5的
3中的数据 - 看第二页
//
// Good Ref. - http://msdn.microsoft.com/en-us/library/ms254937(v=vs.110).aspx
//
// Basic stuff from C# console app
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// Required for data table
using System.Data;
using System.Data.SqlClient;
// Standard stuff ...
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Debug info
Console.WriteLine("Test - Start");
// Create the table with one column
DataTable my_Table;
my_Table = new DataTable("Category");
my_Table.Columns.Add("CategoryId", typeof(string));
// Add data to table
for (int my_Cnt = 50; my_Cnt < 75; my_Cnt++)
{
DataRow my_Row = my_Table.NewRow();
my_Row["CategoryId"] = my_Cnt.ToString();
my_Table.Rows.Add(my_Row);
}
// Debug info
Console.WriteLine("Test - created data set");
// Create a connection
SqlConnection my_Conn;
string str_Conn = "Server=localhost;Database=Test;Trusted_Connection=True;";
my_Conn = new SqlConnection(str_Conn);
// Debug info
Console.WriteLine("Test - create connection");
// Create the command and set its properties.
SqlCommand my_Cmd = new SqlCommand();
my_Cmd.Connection = my_Conn;
my_Cmd.CommandText = "dbo.GetArticlesByPage";
my_Cmd.CommandType = CommandType.StoredProcedure;
// Add parameter 0
SqlParameter my_Parm0 = new SqlParameter();
my_Parm0.ParameterName = "@Tvp";
my_Parm0.SqlDbType = SqlDbType.Structured;
my_Parm0.Direction = ParameterDirection.Input;
my_Parm0.Value = my_Table;
my_Cmd.Parameters.Add(my_Parm0);
// Add parameter 1
SqlParameter my_Parm1 = new SqlParameter();
my_Parm1.ParameterName = "@PageIndex";
my_Parm1.SqlDbType = SqlDbType.Int;
my_Parm1.Direction = ParameterDirection.Input;
my_Parm1.Value = 2;
my_Cmd.Parameters.Add(my_Parm1);
// Add parameter 2
SqlParameter my_Parm2 = new SqlParameter();
my_Parm2.ParameterName = "@PageSize";
my_Parm2.SqlDbType = SqlDbType.Int;
my_Parm2.Direction = ParameterDirection.Input;
my_Parm2.Value = 5;
my_Cmd.Parameters.Add(my_Parm2);
// Add parameter 3
SqlParameter my_Parm3 = new SqlParameter();
my_Parm3.ParameterName = "@PageCount";
my_Parm3.SqlDbType = SqlDbType.Int;
my_Parm3.Direction = ParameterDirection.Output;
my_Parm3.Value = 5;
my_Cmd.Parameters.Add(my_Parm3);
// Open the connection
my_Conn.Open();
// Debug info
Console.WriteLine("Test - execute reader");
// Execute the reader
SqlDataReader my_Reader = my_Cmd.ExecuteReader();
if (my_Reader.HasRows)
{
while (my_Reader.Read())
{
Console.WriteLine("{0}", my_Reader[0].ToString());
}
}
else
{
Console.WriteLine("No rows found.");
}
// Close the reader
my_Reader.Close();
// Number of pages (output after reader - order is important)
Console.WriteLine("Pages = ");
Console.WriteLine(my_Cmd.Parameters["@PageCount"].Value.ToString());
// Close the connection
my_Conn.Close();
// Debug info
Console.WriteLine("Test - close connection");
// Debug info
Console.WriteLine("Test - End");
// Pause to view output
Console.Read();
}
}
}
这里是正确的输出的快照来自C#控制台应用程序。
我要感谢您的提问!
我用C#编码已经有一段时间了。但是就像一辆自行车,不需要很长时间就可以重新开始。 T-SQL示例使用SSMS 2012完成,C#程序使用VS 2013完成。最新和最好的。
好少!
旧式的加入让我痛苦痛苦的眼泪。 – Hogan
@霍根 - 过去 - 现在仍然是 - 最糟糕的绝对缩影。 – Brian
@Hogan如何将我的旧式连接转换为更有效的连接 –