私がこれらの質問を受けるときにまずやることは、サンプルデータベースを作成することです。以下のコードは、以下を作成します。
1 - データベースと命名[テスト]
2 - 名前のテーブル[ディスカッション]
3 -
[CategoryIdArray]という名前のユーザー定義テーブル型 - [CategoryMap]
4という名前の表
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
2番目の手順は、ストアドプロシージャを書き換えることです。 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
は、私が代わりにページ数を残しました。しかし、結果セットが空になるまで呼び出しを繰り返すことができるので、必要とは思われません。
レコードセットを一時テーブルにダンプしないでください。表示するすべてのカラムを返すと、レコードセットがかなり大きくなる可能性があります。私は2つの別々の呼び出しを選択します。 1つは合計カウントです。 1つのページに1つ。
最後の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 - [テスト]データベースで定義されているタイプですか?これをもう一度確認してください。
3 - これは間違いありませんか?カラム名は、データベースタイプの[CategoryId]です。あなたは次の - [Category]を持っています。 C#コードで名前を変更してみてください。
dt_Categories.Columns.Add( "Category"、typeof(String));
4 - [dbo]を削除します。 SPのタイプからこれは、MS SQLのヒントの例ではありません。問題を混乱させるかもしれません。 SQLサーバーがその名前を解決します。
5 - 型がbig intとして定義されているが、テーブルのidがintであることがわかりましたか?データ型が一貫していることを確認してください。
これらの提案をお試しください。あなたの作り方を教えてください。
これはまだ問題がある場合は、詳細なコールスタックトレースとエラーメッセージを受け取ることができますか?
ここに私が約束したC#コンソールアプリケーションがあります。
期待どおりに動作します。
ADO.NETとデータテーブルの基礎となるアイデアをいくつか混在させていました。直接のウィンドウとローカル変数を調べるのに慣れておく必要があります。これは問題を追跡するのに役立ちます。
ここでは、ストアドプロシージャのサンプル呼び出しを示します。
1 - セットアップデータテーブル
2(50 74) - 5の
3によるページデータが - 2ページ目ここ
//
// 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
@Hogan - 最悪のことの絶対的な原型がありました。 – Brian
@Hogan私の古いスタイルの結合をより効率的な結合に変換するにはどうすればいいですか? –