1. 程式人生 > >\t\t在MSSQL中定義和使用C#自定義型別 SQL Server08表型別引數傳遞

\t\t在MSSQL中定義和使用C#自定義型別 SQL Server08表型別引數傳遞

在學習SQL Server 2008的過程中,突然發現SQL Server支援自定義表型別,我們可以輕鬆的將一個SQL Server 2008表型別作為引數傳遞給儲存過程。C#下實現了SQL Server 2008表型別引數傳遞

本示例中用到的型別在資料庫中的位置:
在MSSQL中定義和使用C自定義型別 SQL Server08表型別引數傳遞 - yandavid - 我的部落格
建立一個自定義表型別
CREATE TYPE [dbo].[UserDetailsType] AS TABLE
(
      [ID] [varchar](50) NULL,
      [Name] [varchar](50) NULL,
      [Sex] [varchar](50) NULL,
      [Age] [decimal](18, 0) NULL
)


建立一個名為User的表,結構如下:
在MSSQL中定義和使用C自定義型別 SQL Server08表型別引數傳遞 - yandavid - 我的部落格
建立一個儲存過程
CREATE PROCEDURE [dbo].[InsertUserInfo]
@UserInfo [UserDetailsType] readonly--指示不能在過程的主體中更新或修改引數。如果引數型別為使用者定義的表型別,則必須指定 READONLY
AS
BEGIN

insert into [User]
([ID], [Name], [Sex], [Age])
select [ID], [Name], [Sex], [Age]
from @UserInfo;

END

//啟動Visual Studio 2008,建立一個預設的窗體應用程式後,我們需要先在記憶體中建立一個數據庫表DataTable的例項,如下:
private static DataTable PrepareDatatable()
{
    DataTable dt = new DataTable("dt");
    DataColumn[] dtc = new DataColumn[4];
    dtc[0] = new DataColumn("ID", System.Type.GetType("System.String"));
    dtc[1] = new DataColumn("Name", System.Type.GetType("System.String"));
    dtc[2] = new DataColumn("Sex", System.Type.GetType("System.String"));
    dtc[3] = new DataColumn("Age", System.Type.GetType("System.Decimal"));
    dt.Columns.AddRange(dtc);
    return dt;
}

//然後,通過SqlCommand執行剛才我們建立的Test資料庫儲存過程InsertUserInfo,並傳遞我們在記憶體中建立的DataTable的例項,如下:
private static void SaveUserInfoDetails()
{
    DataTable dt = PrepareDatatable();
    for (int i = 0; i < = 5; i++)
    {
        DataRow dr = dt.NewRow();
        dr[0] = i.ToString();
        dr[1] = "Name" + i.ToString();
        dr[2] = "男";
        dr[3] = (i*10).ToString();
        dt.Rows.Add(dr);
    }
    using (SqlConnection conn = new SqlConnection("server=Rithia;database=Test;integrated security=SSPI"))
    {
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.CommandText = "dbo.InsertUserInfo";

        SqlParameter param = cmd.Parameters.AddWithValue("@UserInfo", dt);
        conn.Open();
        cmd.ExecuteNonQuery();
    }

}

通過上面的示例,我們可以在程式客戶端先建立好要傳遞的表型別資料,然後傳遞給儲存過程,而儲存過程則將SQL Server 2008表型別引數中的記錄一次性的新增到了資料庫實體表中,這種操作在需要傳遞給儲存過程陣列形式的引數時非常非常方便。

--------------原始做法:---------------------------------------------

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace MyDBType
{
    [Serializable]//標記為是可序列化的
    [SqlUserDefinedType(Format.UserDefined, Name = "Person", MaxByteSize = 100)]
    /*
        SqlUserDefinedType特性支援以下屬性:

        Format——用語指定如何在SQL Server資料庫中序列化使用者自定義型別。其取值為Native和UserDefined;

        IsByteOrdered——用於使該自定義使用者型別按其本身的位元組表示方法排序;

        IsFixedLength——用於指定這個型別的所有例項是否都具有相同的長度;

        MaxByteSize——用於指定該使用者自定義型別的最大位元組數;

        Name——用於為使用者自定義型別指定名稱;

        ValidationMethodName——用於指定校驗使用者自定義型別是否有效的方法名稱。

        Format屬性最為重要,他自動使用者自定義型別如何進行序列化,選項設定為Native時是讓SQL Server資料庫自動處理所有序列化問題而不需要使用者做任何額外的操作。
                但原生序列化方式只能應用到簡單類上。如果類公開了非值型別的屬性(如String),那麼該類將不能使用原生序列化。
     */
    public class Person : IBinarySerialize, INullable
    {
        public string Name;
        public int Age;
        public char Sex;

        /// <summary>
        /// 在SQL查詢中對該屬性進行比較操作所必須指定的特性
        /// </summary>
        [SqlFacet(Precision = 38, Scale = 2)]
        public Decimal Account;

        #region IBinarySerialize 成員
        /// <summary>
        /// 用於從BinaryReader物件中讀取資料到類中的屬性
        /// </summary>
        /// <param name="r"></param>
        public void Read(System.IO.BinaryReader r)
        {
            string s = r.ReadString();
            string[] values = s.Split('|');
            Name = values[0];
            if (values.Length > 1) Int32.TryParse(values[1], out Age);
            if (values.Length > 2) Char.TryParse(values[2], out Sex);
            if (values.Length > 3) Decimal.TryParse(values[3], out Account);
        }

        /// <summary>
        /// 把類中的屬性寫入到BinaryReader物件
        /// </summary>
        /// <param name="w"></param>
        public void Write(System.IO.BinaryWriter w)
        {
            w.Write(string.Format("{0}|{1}|{2}|{3}", Name, Age.ToString(), Sex, Account));
        }

        #endregion

        #region INullable 成員
        /// <summary>
        /// 用於在sql中判斷該型別的變數是否為null
        /// </summary>
        public bool IsNull
        {
            get { return string.IsNullOrEmpty(Name); }
        }

        #endregion
        /// <summary>
        /// 實現靜態的返回型別為當前類型別的Null只讀屬性,返回一個在sql中認為為null的例項
        /// </summary>
        public static Person Null
        {
            get
            {
                return new Person { Name = string.Empty };
            }
        }
        /// <summary>
        /// 型別轉換函式
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static Person Parse(SqlString str)
        {
            string[] values = str.Value.Split('|');
            var p = new Person
                        {
                            Name = values[0],
                        };
            if (values.Length > 1) Int32.TryParse(values[1], out p.Age);
            if (values.Length > 2) Char.TryParse(values[2], out p.Sex);
            if (values.Length > 3) Decimal.TryParse(values[3], out p.Account);

            return p;
        }

        public override string ToString()
        {
            return this.IsNull ? "NULL" : string.Format("{0}|{1}|{2}|{3}", Name, Age.ToString(), Sex,Account);
        }
    }
}

---------SQL指令碼

select * from sys.assemblies

--引用該類所在的程式集

CREATE assembly MyType

from 'C:\MyDBType.dll'

go

--建立具體的型別 create type 型別名external name sql中程式集名.[C#類完全限定名]

CREATE TYPE person

external name MyType.[MyDBType.Person]

go

--建立以自定義型別為引數的儲存過程

create proc MyDBTypeTest

@p person

as

print @p.Name

go

--禁止在.Net Framewrok中執行使用者程式碼.啟用"clr enabled"配置選項

--Sql Server中執行這段程式碼可以開啟CLR

exec sp_configure'show advanced options', '1';

go

reconfigure;

go

exec sp_configure'clr enabled', '1'

go

reconfigure;

exec sp_configure'show advanced options', '1';

go

--定義變數

declare @p person

--賦值Parse(SqlString str) 函式派上用場了

set @p = convert(person ,N'David.Yan|30|n|100000.99')

PRINT @p.Account

--執行儲存過程

exec MyDBTypeTest@p

--弄個應該為null的值

set @p = convert(person, '|2|y')

--判斷是不是真為null;

if @p is null

print 'bool IsNull發揮作用了,static Person Null也發揮作用了.真為null'

/*

清理現場

drop proc MyDBTypeTest

drop type person

drop assembly MyType

*/

相關推薦

\t\t在MSSQL定義使用C#定義型別 SQL Server08型別引數傳遞

在學習SQL Server 2008的過程中,突然發現SQL Server支援自定義表型別,我們可以輕鬆的將一個SQL Server 2008表型別作為引數傳遞給儲存過程。C#下實現了SQL Server 2008表型別引數傳遞本示例中用到的型別在資料庫中的位置:建立一個自定義表型別CREATE TYPE [

android:RadioButton定義定義的實現

    我簡單解釋下:當root為null的時候,我們只是把一個xml檔案例項化成View物件,反回的就是xml對應的View.而當root不為null的時候,也就是存在parent.那麼我們將把這個xml例項化程View物件後,將這個View檢視add進其parent中.所以在這裡我們用的是LayoutIn

Java 知識點整理-10.Java集合框架 去除ArrayList重複字串、定義物件 棧佇列 泛型 JDK5新特性 asList() toArray(T[] a) ArrayList迴圈巢狀

詳細標題:去除ArrayList中重複字串、自定義物件元素方式 棧和佇列 泛型 JDK5新特性(增強for迴圈 三種迭代(普通for、迭代器、增強for)中的元素能否刪除 靜態匯入 可變引數)Arrays工具類的asList() Collection中toArray(T[] a) 集合巢狀之Arra

C#定義RSA加密解密及RSA簽名驗證類實例

狀態 share normal evel thumb weight encrypt security clas 本文實例講述了C#自定義RSA加密解密及RSA簽名和驗證類。分享給大家供大家參考。具體分析如下: 這個C#類自定義RSA加密解密及RSA簽名和驗證,包含了RSA

C#定義控制元件美化的RadionButtonCheckButton加入了Image圖示

前段時間剛在CSDN上傳了一個美化的Radionbutton和CheckButton,但是加入imagelist後,顯示不出來,在這裡我對程式碼做了一些更改,希望對大家的學習有幫助。 控制元件效果圖如下: 1.     &nb

C#定義窗體style button點選事件通過Command傳遞

資源字典中 < Button x:Name="BtnClose" Margin="0,-1.5,-1,0" Style="{DynamicResource ButtonClose}" HorizontalAlignment="Right" Vertic

c# 通過json.net的JsonConverter進行定義序列化與反序列化

iter 希望 生成 ade json.net .json implement else col   相信大家在工作中會經常遇見對json進行序列化與反序列化吧,但通常的序列化與反序列化中的json結構與c#中的類模型結構是相對應的,我們是否可以在序列化一個對象時候,讓我們

一對一視訊交友原始碼關於圖片載入部分定義控制元件的原始碼

有這麼一部分原始碼,他們不如音視訊採集、播放部分的原始碼顯得那麼重要,但他們的存在使頁面看起來更美觀流暢,他們就是: 一、關於圖片載入的一段程式碼: 1、載入原圖,即沒有壓縮、裁剪、變換之前的圖,保持了原圖的大小、尺寸和解析度。 public static void displaySou

C#定義操作主窗體控制元件,通過委託實現

主窗體中包含一個標籤label1和一個按鈕button1 程式碼如下: public void ChangeLabel(string text) { label1.Text = text; } private void button1_Click(o

GCC/G++編譯器VS IDE的一些預定義巨集使用者定義巨集

預定義巨集,  編譯器通常會根據平臺和編譯選項的不同,為被編譯的程式提供不同的預定義的巨集, 例如WIN32 WIN64 LINUX, 例如DEBUG, RELEASE. 1. 在使用gcc/g++編譯器時,可以通過以下命令打印出編譯器預編譯的巨集。 gcc -dM -E - < /dev/null

.net web api 呼叫post方法呼叫定義方法名session使用

        在開發web api的時候我們需要呼叫post方法或自定義的方法的時候,還有使用session來儲存相關的資料,首先我介紹一下如何在web api中使用session,在使用session的時候我們需要配置儲存session機制,啟用session功能,在G

C#開發學習筆記:向Dev控制元件庫的GridControl新增定義複選框

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Dev控制元件庫自帶的有複選框列,預設是不顯示狀態,如果需要則設定相關

C++關於set的定義排序函式的書寫

大概有兩個月沒用過C++啦,手都變得很生了,在這裡,在這裡我想扯一下關於set的比較函式的定義,我想,應該有不少人對這個東西感到頭疼吧! 如果說我想在set裡面新增一個自定義的型別,比如說下面的結構體: struct Symbol { char

微信小程序-隱藏顯示定義的導航

傳值 hat ebs doc isp pre code nav aaa 微信小程序中不能直接操作window對象,document文檔,跟html的樹結構不相同。 實現類似導航的隱藏顯示,如圖效果: 點擊網絡顯示或隱藏網絡中包含的內容。其他類似。 如果是jquer

數據庫的異常(預定義,非預定義,用戶定義)

out where output 數據 sel || 非預定義異常 code err DECLARE --預定義 異常信息 不聲明異常 v_empno emp.empno%TYPE :=&empno; v_sal emp.sal%TY

C# 定義Exception

ges 特定 ati log exce 系統 pri ado 函數 有時需要區分不同的自定義錯誤,也可能需要特定的錯誤參數,此時需要自定義一些Exception類,而方法也很簡單,簡單的說需要繼承Exception及其構造函數。 有時為了只調用特定參數,可以把其他構造函數設

在Web.config或App.config的添加定義配置

base .com har 信息 key 需要 lin xml文件 item .Net中的System.Configuration命名空間為我們在web.config或者app.config中自定義配置提供了完美的支持。最近看到一些項目中還在自定義xml文件做程序的配置,所

c#定義

入棧 exceptio csharp 排隊 private 大小 val sta 先進後出 棧的原理是先進後出。隊列是先進先出。棧像乘坐電梯,後進的先出去。隊列就是排隊。 實現代碼: public class myStack<T> {

C#定義處理xml數據類實例

行數 tostring 圖片 跑步 判斷 rose bool ati map 本文實例講述了C#自定義處理xml數據類。分享給大家供大家參考。具體分析如下: 這個C#類專門用戶處理xml數據,可以大大簡化xml的操作,類中封裝了常用的xml操作,包括打開、讀取xml數據,

C#定義針對URL地址的處理類實例

new expr 操作方法 border int ignore n) spec $2 本文實例講述了C#自定義針對URL地址的處理類。分享給大家供大家參考。具體分析如下: 這個C#類是專門針對URL網址處理的類,可以對URL地址進行Base64的加密和解密,可以通過函數的