使用Microsoft.Practices.EnterpriseLibrary.Data调用存数过程Output参数注意事项

最近拿了一个开源的源码看了下,在调试的过程中发现调用存数过程的output参数的时候一直出错,现在将问题记录下来。

问题描述:

1. 使用Microsoft.Practices.EnterpriseLibrary.Data.dll调用数据库

2. 存数过程如下:

USE [Survey]
GO
/****** Object:  StoredProcedure [dbo].[vts_spQuestionCopy]    Script Date: 08/03/2014 19:11:10 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
/*
/// <summary>
/// Copy an existing question to another survey
/// </summary>
*/
ALTER PROCEDURE [dbo].[vts_spQuestionCopy]
                @QuestionID int,
                @NewSurveyID int,
                @DisplayOrder int,
                @PageNumber int,
                @QuestionCopyID int output
AS

BEGIN TRANSACTION CopyQuestion

INSERT INTO vts_tbQuestion
    (ParentQuestionId,
    SurveyID,
    LibraryID,
    SelectionModeId,
    LayoutModeId,
    DisplayOrder,
    PageNumber,
    MinSelectionRequired,
    MaxSelectionAllowed,
    RatingEnabled,
    ColumnsNumber,
    RandomizeAnswers,
    QuestionText,
    QuestionPipeAlias,
    QuestionIDText,
    HelpText,
    Alias,
    QuestiongroupID,
    ShowHelpText)
SELECT
    ParentQuestionId,
    @NewSurveyID,
    null,
    SelectionModeId,
    LayoutModeId,
    @DisplayOrder,
    @PageNumber,
    MinSelectionRequired,
    MaxSelectionAllowed,
    RatingEnabled,
    ColumnsNumber,
    RandomizeAnswers,
    QuestionText,
    QuestionPipeAlias,
    QuestionIDText,
    HelpText,
    Alias,
    QuestionGroupID,
    ShowHelpText
FROM vts_tbQuestion WHERE QuestionId = @QuestionID

-- Check if the cloned question was created
IF @@rowCount <> 0
BEGIN
    -- Clone the question‘s answers
    set @QuestionCopyID = convert(int,Scope_Identity())
    INSERT INTO vts_tbMultiLanguageText(LanguageItemID, LanguageCode, LanguageMessageTypeID, ItemText)
        SELECT @QuestionCopyID as LanguageItemID, LanguageCode, LanguageMessageTypeID, ItemText
        FROM vts_tbMultiLanguageText
        WHERE LanguageItemID = @QuestionID AND LanguageMessageTypeID in(3,10,11,12)    

    exec vts_spQuestionChildsClone @QuestionID, @QuestionCopyID, @NewSurveyID
    UPDATE vts_tbQuestion SET DisplayOrder = @DisplayOrder, PageNumber = @PageNumber
    WHERE SurveyID = @NewSurveyID AND ParentQuestionid = @QuestionCopyID

    exec vts_spAnswersCloneByQuestionId @QuestionID, @QuestionCopyID

    exec vts_spQuestionSectionOptionClone @QuestionID, @QuestionCopyID

    -- Update the display order
    UPDATE vts_tbQuestion
    SET DisplayOrder = DisplayOrder + 1
    WHERE
        SurveyID = @NewSurveyID AND
        ((QuestionID<>@QuestionCopyID AND ParentQuestionID is null) OR
         (ParentQuestionID is not null AND ParentQuestionID <> @QuestionCopyID)) AND
         DisplayOrder >= @DisplayOrder
END

COMMIT TRANSACTION CopyQuestion

3. 代码中的调用过程如下:

        public int CopyQuestionById(int questionId, int targetSurveyId, int targetDisplayOrder, int targetPageNumber)
        {
            //SqlParameter[] commandParameters = new SqlParameter[]
            //{ new SqlParameter("@QuestionId", questionId),
            //    new SqlParameter("@NewSurveyId", targetSurveyId),
            //    new SqlParameter("@DisplayOrder", targetDisplayOrder),
            //    new SqlParameter("@PageNumber", targetPageNumber),
            //    new SqlParameter("@QuestionCopyId", SqlDbType.Int)
            //};
            //commandParameters[4].Direction = ParameterDirection.Output;

            ArrayList commandParameters = new ArrayList();
            {
                commandParameters.Add(new SqlParameter("@QuestionId", questionId).SqlValue);
                commandParameters.Add(new SqlParameter("@NewSurveyId", targetSurveyId).SqlValue);
                commandParameters.Add(new SqlParameter("@DisplayOrder", targetDisplayOrder).SqlValue);
                commandParameters.Add(new SqlParameter("@PageNumber", targetPageNumber).SqlValue);
                commandParameters.Add(new SqlParameter("@QuestionCopyId", SqlDbType.Int) { Direction = ParameterDirection.Output}.SqlValue);
            }

            DbConnection.db.ExecuteNonQuery("vts_spQuestionCopy", commandParameters);
            return int.Parse(commandParameters[4].ToString());
        }

咱们来分析一下这段代码:在调用的使用一直提示一个错误

new SqlParameter("@QuestionCopyId", SqlDbType.Int) { Direction = ParameterDirection.Output}.SqlValue

为空。原来当为Output时,sqlvalue就会为空,现在我们应该怎么办呢?

我尝试给其一个默认值,将代码修改为

new SqlParameter("@QuestionCopyId", SqlDbType.Int) { Direction = ParameterDirection.Output, Value = 0}.SqlValue

新的问题出现了:

An exception of type ‘System.InvalidOperationException‘ occurred in Microsoft.Practices.EnterpriseLibrary.Data.dll but was not handled in user code

Additional information: The number of parameters does not match number of values for stored procedure. 

ExecuteNonQuery(string storedProcedureName, params object[] parameterValues)

这个错误是什么意思呢?意思是说参数个数不一致。查询后得知,原来 params 传的是值,当Output有默认值的时候,传入参数就为5个,可是存储过程只接受4个。现在应该怎么办呢?

尝试修改

DbConnection.db.ExecuteNonQuery("vts_spQuestionCopy", commandParameters.ToArray());

但是还是会报错,同样的错误。尝试去掉默认值,使用上述方法,成功运行,但是想取到返回值就懵了,取不到。肿么办?

尝试使用ExecuteNonQuery(DbCommand command),将代码修改如下:

        public int CopyQuestionById(int questionId, int targetSurveyId, int targetDisplayOrder, int targetPageNumber)
        {
            SqlParameter[] commandParameters = new SqlParameter[]
            { new SqlParameter("@QuestionId", questionId),
                new SqlParameter("@NewSurveyId", targetSurveyId),
                new SqlParameter("@DisplayOrder", targetDisplayOrder),
                new SqlParameter("@PageNumber", targetPageNumber),
                new SqlParameter("@QuestionCopyId", SqlDbType.Int)
            };
            commandParameters[4].Direction = ParameterDirection.Output;

            SqlCommand vts_spQuestionCopy = new SqlCommand("vts_spQuestionCopy");
            vts_spQuestionCopy.CommandType = CommandType.StoredProcedure;
            vts_spQuestionCopy.Parameters.AddRange(commandParameters);
            DbConnection.db.ExecuteNonQuery(vts_spQuestionCopy);

            var result =int.Parse(vts_spQuestionCopy.Parameters["@QuestionCopyID"].Value.ToString());
            return result;
        }

运行成功,取到output返回值。

Note:ExecuteNonQuery(string storedProcedureName, params object[] parameterValues)中的params其实是将SqlParameter中的值传入。想要取到output返回值的时候,可能会存在问题。目前我是使用ExecuteNonQuery(DbCommand command)来得到返回值,各位如果有其它方法,敬请留下,谢谢。

使用Microsoft.Practices.EnterpriseLibrary.Data调用存数过程Output参数注意事项,布布扣,bubuko.com

时间: 2024-10-23 11:12:02

使用Microsoft.Practices.EnterpriseLibrary.Data调用存数过程Output参数注意事项的相关文章

在WebService中使用Microsoft.Practices.EnterpriseLibrary.Data配置数据库

1. 新建WebApplication1项目 1.1 新建—Web—ASP.NET Empty Web Application--WebApplication1 1.2 添加一个WebForm1 2. 新建webService项目 2.1 新建—Web—ASP.NET Empty Web Application—WebApplicationService 2.2 选择WebApplicationService—右键—Add—WebService (ASMX)-- WebServiceGSS.as

Microsoft.Practices.EnterpriseLibrary

项目中使用了Microsoft.Practices.EnterpriseLibrary这个东西,根据名字猜测和微软有关系(可以翻译为:微软实践企业库). 看到了引入了两个命名空间: using Microsoft.Practices.EnterpriseLibrary.Data; using Microsoft.Practices.EnterpriseLibrary.Data.Sql; 在项目引用中发现了三个相关的dll文件: Microsoft.Practices.EnterpriseLibr

Could not load file or assembly &#39;Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, ...

使用oracle数据库一个多月依赖这问题一直都得不到解决,最近任务不是很忙了,所以决定把这问题解决掉.写一篇文章做记录. 以上错误主要是net程序oracle数据库使用了Microsoft Enterprise Library 5.0 类库访问oracle数据库,其具有优秀的访问不通数据库的能力.使用方法不对也同样出现错误.解决办法是下载http://www.microsoft.com/en-us/download/confirmation.aspx?id=15104最新的类库并安装,安装后到安

Microsoft.Practices.EnterpriseLibrary企业库问题

System.Configuration.ConfigurationErrorsException: Invalid TraceListenerData type in configuration 'listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.Enterpr

表连接、存数过程及基本编程

一.表连接:将多个表的数据一次性查询出来,共同显示(一).横向连接1.子查询方式:select (select 字段名 from 表名称a where 表名称A.字段名a = 表名称B.字段名a),字段名,字段名 from 表名称B 2.笛卡尔积:select 字段名,字段名 from 表名称A,表名称B where 表名称A .字段名a = 表名称B.字段名a 3.join on:select 字段名,字段名 from 表名称A join 表名称B on 表名称A .字段名a = 表名称B.字

EF 怎么调用存储过程并获得output参数

1.MVC4的项目,自动会把存储过程在项目中映射为函数. 2.存储过程: 1 ALTER PROCEDURE [dbo].[P_FindAnZhiRen] 2 @tempP_ID int output 3 ,@Member_ID int 4 ,@Is_Right bit 5 AS 6 7 8 set @tempP_ID =@Member_ID 9 BEGIN 10 11 12 if @Is_Right =0 13 begin 14 While(Exists(select 1 from tbMem

第九回 Microsoft.Practices.Unity.Interception实现基于数据集的缓存(针对六,七,八讲的具体概念和配置的解说)

返回目录 概念 Microsoft.Practices.Unity.Interception是一个拦截器,它隶属于Microsoft.Practices.Unity组成之中,主要完成AOP的功能,而实现AOP方法拦截(页向切面)的基础就是IoC,我们需要配置相关接口或者类型的IoC方式,然后在生产对象时,使用Unity的方法进行动态生产对象,这时,你的Interception拦截器也会起作用! 相关技术 IoC: 控制反转(Inversion of Control,英文缩写为IoC)是一个重要的

EF 调用存储过程、返回多结果集和OUTPUT参数 等问题

一.EF调用存储过程: 1.执行返回表类型的存储过程 先上存储过程 随手写的一个最简单的   .        Student.  Enrollment,Student   Enrollment.StudentIDStudent.StudentID  Enrollment.StudentID 执行存储过程的方法 是用直接执行sql的方式 我在我的文章第九篇 有过详细的介绍~大家可以先去看下 执行表的存储过程 其实是非常强大的 延迟加载 等都有体现 博客园的陆老师已经写了 写的非常清楚了~我这里就

使用Microsoft.Practices.Unity 依赖注入

Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入(Constructor Injection).属性注入(Property Injection),以及方法调用注入(Method Call Injection). 假设我们有下面的场景代码,在代码里面有一个很简单的customer对象,customer 对象有个save 方法, 这个方法通过调用ICusto