使用参数调用存储过程时,SqlScalar <t>和SqlList <t>出现问题</t> </t>

时间:2013-03-20 09:07:56

标签: servicestack ormlite-servicestack

Servicestack.OrmLite的新API规定,在调用fx存储过程时,您应该使用SqlScalar或SqlList,如下所示:

List<Poco> results = db.SqlList<Poco>("EXEC GetAnalyticsForWeek 1");
List<Poco> results = db.SqlList<Poco>("EXEC GetAnalyticsForWeek @weekNo", new { weekNo = 1 });

List<int> results = db.SqlList<int>("EXEC GetTotalsForWeek 1");
List<int> results = db.SqlList<int>("EXEC GetTotalsForWeek @weekNo", new { weekNo = 1 });

但是命名的参数不起作用。您必须遵守SP中参数的顺序。我认为这是因为SP是使用CommandType = CommandType.Text而不是CommandType.StoredProcedure执行的,并且参数被添加为dbCmd.Parameters.Add()。似乎因为CommandType是Text,它希望将参数添加到SQL查询字符串中,而不是作为Parameters.Add(),因为它忽略了命名。 一个例子:

CREATE PROCEDURE [dbo].[sproc_WS_SelectScanFeedScanRecords] 
    @JobNo int = 0
   ,@SyncStatus int = -1
AS
BEGIN
    SET NOCOUNT ON;
    SELECT 
      FSR.ScanId
    , FSR.JobNo
    , FSR.BatchNo
    , FSR.BagNo
    , FSR.ScanType
    , FSR.ScanDate
    , FSR.ScanTime
    , FSR.ScanStatus
    , FSR.SyncStatus
    , FSR.JobId
    FROM dbo.SCAN_FeedScanRecords FSR
    WHERE ((FSR.JobNo = @JobNo) OR (@JobNo = 0) OR (ISNULL(@JobNo,1) = 1))
    AND   ((FSR.SyncStatus = @SyncStatus) OR (@SyncStatus = -1) OR (ISNULL(@SyncStatus,-1) = -1))
END

以此格式调用此SP:

db.SqlList<ScanRecord>("EXEC sproc_WS_SelectScanFeedScanRecords @SyncStatus",new {SyncStatus = 1});

它返回JobNo = 1而不是SyncStatus = 1的所有记录,因为它忽略了命名参数,并按SP在SP中定义的顺序添加。 我必须这样称呼它:

db.SqlList<ScanRecord>("EXEC sproc_WS_SelectScanFeedScanRecords @SyncStatus=1");

这是预期的行为吗?如果我不相信它,我认为它会破坏匿名类型参数

TIA

1 个答案:

答案 0 :(得分:3)

我的解决方案是为存储过程推送自己的方法。如果人们发现它们很方便,我可以将它们添加到项目中

    public static void StoredProcedure(this IDbConnection dbConn, string storedprocedure, object anonType = null)
    {
        dbConn.Exec(dbCmd =>
        {
            dbCmd.CommandType = CommandType.StoredProcedure;
            dbCmd.CommandText = storedprocedure;
            dbCmd.SetParameters(anonType, true);
            dbCmd.ExecuteNonQuery();
        });
    }
    public static T StoredProcedureScalar<T>(this IDbConnection dbConn, string storedprocedure, object anonType = null)
    {
        return dbConn.Exec(dbCmd =>
        {
            dbCmd.CommandType = CommandType.StoredProcedure;
            dbCmd.CommandText = storedprocedure;
            dbCmd.SetParameters(anonType, true);
            using (IDataReader reader = dbCmd.ExecuteReader())
                return GetScalar<T>(reader);
        });
    }
    public static List<T> StoredProcedureList<T>(this IDbConnection dbConn, string storedprocedure, object anonType = null)
    {
        return dbConn.Exec(dbCmd =>
        {
            dbCmd.CommandType = CommandType.StoredProcedure;
            dbCmd.CommandText = storedprocedure;
            dbCmd.SetParameters(anonType, true);
            using (var dbReader = dbCmd.ExecuteReader())
                return IsScalar<T>()
                    ? dbReader.GetFirstColumn<T>()
                    : dbReader.ConvertToList<T>();
        });
    }

它们只是SqlScalar和SqlList的修改版本加上ExecuteNonQuery