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

相关文章
相关标签/搜索