Git.Framework 框架隨手記--存儲過程簡化

  在不少的ORM中對存儲過程操做都是一個棘手的地方,由於存儲過程是一段預編譯的代碼,其中能夠包含不少處理過程。在Git.Framework中也一樣存在這樣的問題,目前沒有能力解決這個問題。可是對於存儲過程的一些外圍操做目前仍是能夠支持的。html

    上一篇文章簡單回顧地址,可能對了解本文有益: Git.Framework 框架隨手記--SQL配置文件的使用git

  一. 結構簡單說明github

    在前面操做基本SQL的時候咱們已經知道使用對象模型映射其相關的表,一些基本的操做咱們都可以實現完成。在很大的程度上完成了抽象工做,在實現存儲過程的時候咱們贊成遵循抽象的原則。每個存儲過程咱們都映射成爲一個實體類,而這個存儲過程的實體類也必須繼承自BaseEntity。先簡單看看以下一個存儲過程的映射類。app

/*******************************************************************************
 * Copyright (C) Git Corporation. All rights reserved.
 *
 * Author: 代碼工具自動生成
 * Create Date: 2014/03/02 09:57:38
 * Blog: http://www.cnblogs.com/qingyuan/ 
 * Description: Git.Framework
 * 
 * Revision History:
 * Date         Author               Description
 * 2014/03/02 09:57:38
*********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Git.Framework.ORM;

namespace Git.Storage.Entity.InStorage
{
    [TableAttribute(DbName = "JooShowGit", Name = "Proc_AuditeInStorage",  IsInternal = false,MapType=MapType.Proc)]
    public partial class Proc_AuditeInStorageEntity:BaseEntity
    {
        public Proc_AuditeInStorageEntity()
        {
        }

        [DataMapping(ColumnName = "OrderNum", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string OrderNum { get;  set; }

        [DataMapping(ColumnName = "Status", DbType = DbType.Int32, Length = 4000,ColumnType=ColumnType.InPut)]
        public Int32 Status { get;  set; }

        [DataMapping(ColumnName = "AuditUser", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string AuditUser { get;  set; }

        [DataMapping(ColumnName = "Reason", DbType = DbType.String, Length = 400,ColumnType=ColumnType.InPut)]
        public string Reason { get;  set; }

        [DataMapping(ColumnName = "OperateType", DbType = DbType.Int32, Length = 4000,ColumnType=ColumnType.InPut)]
        public Int32 OperateType { get;  set; }

        [DataMapping(ColumnName = "EquipmentNum", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string EquipmentNum { get;  set; }

        [DataMapping(ColumnName = "EquipmentCode", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string EquipmentCode { get;  set; }

        [DataMapping(ColumnName = "Remark", DbType = DbType.String, Length = 400,ColumnType=ColumnType.InPut)]
        public string Remark { get;  set; }

        [DataMapping(ColumnName = "ReturnValue", DbType = DbType.String, Length = 50,ColumnType=ColumnType.InOutPut)]
        public string ReturnValue { get;  set; }

    }
}
存儲過程映射類

    上面這個實體類第一眼看和以前的沒有什麼區別,若是觀察仔細這裏仍是有小小的區別的,在某些標識特性上存在着差別。框架

[TableAttribute(DbName = "JooShowGit", Name = "Proc_AuditeInStorage",  IsInternal = false,MapType=MapType.Proc)]

    在前面TableAttribute是指定的表的映射,這裏一樣適用於存儲過程的的標識。可是這裏多了一個標識符,MapType=MapType.Proc. 指定映射爲存儲過程,默認狀況是Table 和View的映射。前面沒有提到View,View在結構上和Table沒有太大的差別,因此直接將View當作Table使用便可。ide

[DataMapping(ColumnName = "OrderNum", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
public string OrderNum { get;  set; }

    這是一個字段映射的過程,和以前也沒有什麼區別,可是這裏彷佛有不少屬性沒有了,由於沒有任何意義,因此不填寫也不要緊,即便填寫了不得任何做用。可是這裏須要制定一個ColumnType屬性,上一篇講到了參數類型有幾種類型,這裏就是指定其類型的。上面一段代碼則是指定這個字段爲輸入參數。函數

[DataMapping(ColumnName = "ReturnValue", DbType = DbType.String, Length = 50,ColumnType=ColumnType.InOutPut)]
public string ReturnValue { get;  set; }

    這段代碼這是指定了一個屬性字段爲輸出參數類型,在調用存儲過程執行成功以後,存儲過程返回的值會自動填充到這個屬性中,不須要咱們作任何其餘的處理,仍是比較方便。工具

public enum ColumnType
{
        InPut = 1,
        OutPut = 2,
        InOutPut = 3,
        Return = 4,
        Common = 10,
}
字段類型枚舉值的定義

    這個枚舉值就是ColumnType的詳細定義,總共有有5中定義,可是其中用到的最多也就是4種,都是咱們比較熟悉的。ui

 

  二. 存儲過程接口的定義this

    在前面已經說過了,這個框架都遵循必定程度的抽象,不管是對錶,視圖,存儲過程,仍是函數咱們都遵循必定規則的抽象。存儲過程是一段已編譯的代碼,而因爲存儲過程的自己複雜性,在不少ORM框架中都對存儲過程支持的不是那麼完全。該框架也是如此,可是在某種程度上仍是能夠完成通常性工做的。對於存儲過程的支持,咱們這裏採用另外的一個接口形式。

public interface IDbProcHelper<T> : IDisposable where T : Git.Framework.ORM.BaseEntity
{
        V ExceuteEntity<V>(T entity) where V : class, new();
        List<V> ExceuteEntityList<V>(T entity) where V : class, new();
        int ExecuteNonQuery(T entity);
        V ExecuteScalar<V>(T entity);
        object ExecuteScalar(T entity);
}
存儲過程抽象接口

    上面這段代碼就是對存儲過程操做的公共接口,其中只有5個方法,相比IDbHelper<T>要簡單多了,並且其中這五個方法的方法名和ADO.NET中定義的同樣,這樣是爲了更好簡單的從ADO.NET過渡到這個上面來。

public partial interface IProc_AuditeInStorage : IDbProcHelper<Proc_AuditeInStorageEntity>
{
}

    這裏是一個存儲過程對應的接口,該存儲過程必須繼承自抽象接口IDbProcHelper<T>,在上面提到過了,繼承這個抽象接口意味着具備其全部的方法,同時也指明瞭這個接口具體操做哪一個存儲過程。其接口實現過程以下:

public partial class Proc_AuditeInStorageDataAccess : DbProcHelper<Proc_AuditeInStorageEntity>, IProc_AuditeInStorage
{
        public Proc_AuditeInStorageDataAccess()
        {
        }

}
存儲過程實現類

    上面這段代碼是存儲過程接口的實現,從結構上和以前說的結構沒有任何區別,執行繼承的類稍微作了一些修改。並且必須遵循這種結構,這是保證運行的基礎。有人會問是否是可使用配置作的更加靈活一點,答案是的,可是我我的遵循的觀點是"約束大於配置"。

 

  三. 如何使用

    存儲過程的使用也很是簡單,和以前的操做沒有太大的區別。在使用以前咱們先建好存儲過程。

    (1) 新建一個存儲過程

----------------------------------------------------------------------------------------------------------------
--*******************************************入庫審覈存儲過程***************************************************
--**************************************************************************************************************
-- 1000 審覈成功
-- 1001 入庫單不存在
-- 1002 入庫單已經審覈
----------------------------------------------------------------------------------------------------------------
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE NAME = 'Proc_AuditeInStorage')
DROP PROCEDURE Proc_AuditeInStorage
GO
CREATE PROCEDURE Proc_AuditeInStorage
(
    @OrderNum        VARCHAR(20),--入庫單號
    @Status            int,--審覈狀態
    @AuditUser        nvarchar(20),--審覈人編號
    @Reason            nvarchar(400),    --審覈成功或者失敗的緣由
    @OperateType    int,    --操做方式 1 電腦 2 PDA
    @EquipmentNum    varchar(20),    --設備編號[所使用的設備編號]
    @EquipmentCode    varchar(20),    --設備條碼[若是沒有就直接設備編號]
    @Remark            nvarchar(400),--入庫單描述
    @ReturnValue    varchar(50) OUTPUT                                                                
)
AS
BEGIN
    --判斷入庫單是否存在
    IF NOT EXISTS ( SELECT COUNT(*) FROM InStorage WHERE OrderNum=@OrderNum AND IsDelete=0)
    BEGIN
        SET @ReturnValue='1001'
        RETURN
    END

    --判斷入庫單是否已經被審覈  查詢入庫單等待審覈是否存在
    IF NOT EXISTS ( SELECT COUNT(*) FROM InStorage WHERE OrderNum=@OrderNum AND Status=1 AND IsDelete=0)
    BEGIN
        SET @ReturnValue='1002'
        RETURN
    END
    
    DECLARE @ProductName nvarchar(100)
    DECLARE @BarCode varchar(50)
    DECLARE @ProductNum varchar(50)
    DECLARE @BatchNum nvarchar(20)
    DECLARE @Num int
    DECLARE @LocalNum varchar(20)
    DECLARE    @StorageNum varchar(20)
    
    DECLARE MyCursor CURSOR FOR SELECT [ProductName],[BarCode],[ProductNum],[BatchNum],[Num],[LocalNum],[StorageNum]  FROM InStorDetail  WHERE OrderNum= @OrderNum
    OPEN MyCursor FETCH NEXT  FROM MyCursor INTO @ProductName, @BarCode,@ProductNum,@BatchNum,@Num,@LocalNum,@StorageNum 
    WHILE @@FETCH_STATUS = 0
    BEGIN
        
        --盤點庫存是否存在
        IF (SELECT COUNT(*) FROM LocalProduct WHERE ProductNum=@ProductNum AND StorageNum=@StorageNum AND LocalNum=@LocalNum)>0
        BEGIN
            --若是存在則修改相應的庫存數量
            UPDATE LocalProduct SET Num=Num+@Num WHERE ProductNum=@ProductNum AND StorageNum=@StorageNum AND LocalNum=@LocalNum
        END
        ELSE
        BEGIN
            --若是不存在則添加

            --得到SN流水號
            DECLARE @SN varchar(50)
            EXEC Proc_SwiftNum '','LocalProduct',@SN OUTPUT
        
            DECLARE @StorageName nvarchar(50)
            DECLARE @LocalName    nvarchar(50)
            DECLARE @LocalType    int
            DECLARE @UserName nvarchar(50)
            
            SELECT TOP 1 @StorageName=StorageName FROM Storage WHERE StorageNum=@StorageNum
            SELECT TOP 1 @LocalName=LocalName,@LocalType=LocalType FROM Location WHERE LocalNum=@LocalNum AND StorageNum=@StorageNum
            SELECT TOP 1 @UserName=UserName FROM Admin WHERE UserCode=@AuditUser
            
            INSERT INTO [dbo].[LocalProduct]([Sn],[StorageNum],[StorageName],[LocalNum],[LocalName],[LocalType],[ProductNum],[BarCode],[ProductName],[Num],[CreateTime],[CreateUser],[CreateName],[Remark])
            VALUES(@SN,@StorageNum,@StorageName,@LocalNum,@LocalName,@LocalType,@ProductNum,@BarCode,@ProductName,@Num,GETDATE(),@AuditUser,@UserName,'')
        END
        
        --入庫臺帳記錄生成
        INSERT INTO [dbo].[InventoryBook]([ProductNum],[BarCode],[ProductName],[Num],[Type],[ContactOrder],[FromLocalNum],[ToLocalNum],[StoreNum],[CreateTime],[CreateUser])
        VALUES(@ProductNum,@BarCode,@ProductName,@Num,1,@OrderNum,'',@LocalNum,@StorageNum,GETDATE(),@AuditUser)
        
        --進行下一個遊標循環
        FETCH NEXT  FROM MyCursor INTO @ProductName, @BarCode,@ProductNum,@BatchNum,@Num,@LocalNum,@StorageNum 
    END

    CLOSE MyCursor
    DEALLOCATE MyCursor--釋放遊標

    --修改訂單狀態
    UPDATE InStorage SET Status=@Status,AuditUser=@AuditUser,AuditeTime=GETDATE(),Reason=@Reason,OperateType=@OperateType,
    EquipmentNum=@EquipmentNum,EquipmentCode=@EquipmentCode,Remark=@Remark
    WHERE OrderNum=@OrderNum

    SET @ReturnValue='1000'
END
GO
新建一個存儲過程

     上面的代碼新建了一個存儲過程,這段代碼是咱們開發的一個條碼倉庫系統中的一個存儲過程,相對比較簡單其中有多個輸入參數,同時也有一個輸出參數。

    (2) 使用工具映射生成實體類

/*******************************************************************************
 * Copyright (C) Git Corporation. All rights reserved.
 *
 * Author: 代碼工具自動生成
 * Create Date: 2014/03/02 09:57:38
 * Blog: http://www.cnblogs.com/qingyuan/ 
 * Description: Git.Framework
 * 
 * Revision History:
 * Date         Author               Description
 * 2014/03/02 09:57:38
*********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Git.Framework.ORM;

namespace Git.Storage.Entity.InStorage
{
    [TableAttribute(DbName = "JooShowGit", Name = "Proc_AuditeInStorage",  IsInternal = false,MapType=MapType.Proc)]
    public partial class Proc_AuditeInStorageEntity:BaseEntity
    {
        public Proc_AuditeInStorageEntity()
        {
        }

        [DataMapping(ColumnName = "OrderNum", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string OrderNum { get;  set; }

        [DataMapping(ColumnName = "Status", DbType = DbType.Int32, Length = 4000,ColumnType=ColumnType.InPut)]
        public Int32 Status { get;  set; }

        [DataMapping(ColumnName = "AuditUser", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string AuditUser { get;  set; }

        [DataMapping(ColumnName = "Reason", DbType = DbType.String, Length = 400,ColumnType=ColumnType.InPut)]
        public string Reason { get;  set; }

        [DataMapping(ColumnName = "OperateType", DbType = DbType.Int32, Length = 4000,ColumnType=ColumnType.InPut)]
        public Int32 OperateType { get;  set; }

        [DataMapping(ColumnName = "EquipmentNum", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string EquipmentNum { get;  set; }

        [DataMapping(ColumnName = "EquipmentCode", DbType = DbType.String, Length = 20,ColumnType=ColumnType.InPut)]
        public string EquipmentCode { get;  set; }

        [DataMapping(ColumnName = "Remark", DbType = DbType.String, Length = 400,ColumnType=ColumnType.InPut)]
        public string Remark { get;  set; }

        [DataMapping(ColumnName = "ReturnValue", DbType = DbType.String, Length = 50,ColumnType=ColumnType.InOutPut)]
        public string ReturnValue { get;  set; }

    }
}
Proc_AuditeInStorageEntity 存儲過程實體類

      上面已經講到了這段代碼的含義,這裏不在累述。

    (3)作好接口的繼承以及實現

      上面已經說到了接口繼承和和實現,這裏不在貼代碼,由於結構是同樣的。

    (4)調用存儲過程返回值

Proc_AuditeInStorageEntity auditeEntity = new Proc_AuditeInStorageEntity();
auditeEntity.OrderNum = entity.OrderNum;
auditeEntity.Status = entity.Status;
auditeEntity.AuditUser = entity.AuditUser;
auditeEntity.Reason = entity.Reason;
auditeEntity.OperateType = entity.OperateType;
auditeEntity.EquipmentNum = entity.EquipmentNum;
auditeEntity.EquipmentCode = entity.EquipmentCode;
auditeEntity.Remark = entity.Remark;
int line = this.Proc_AuditeInStorage.ExecuteNonQuery(auditeEntity);
return auditeEntity.ReturnValue;
調用存儲過程

      上面這段就是調用存儲過程而且返回輸出參數的案例,咱們將存儲過程的參數映射爲一個對象了,在調用存儲過程的時候直接將對象傳入自動處理輸入輸出參數。能夠從上面的代碼看到,輸出參數會自動封裝到傳入的類中指定的屬性中去。

 

    使用案例下載連接:http://pan.baidu.com/s/1sj6S4yT     

    由於這個系列的文章所涉及的東西全是公司項目的的部分截取,非主觀臆斷的編碼和設計,是諸多項目的實戰所積累,因此不便徹底透漏,望請見諒。若是您想有跟深層次的瞭解能夠加羣號: 88718955 


做者:情緣
出處:http://www.cnblogs.com/qingyuan/
關於做者:從事倉庫,生產軟件方面的開發,在項目管理以及企業經營方面尋求發展之路
版權聲明:本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。
聯繫方式: 我的QQ  821865130 ; 倉儲技術QQ羣 88718955,142050808 ;
吉特倉儲管理系統 開源地址: https://github.com/hechenqingyuan/gitwms

相關文章
相關標籤/搜索