簡體   English   中英

將數據表傳遞到存儲過程時,c#System.InvalidCastException

[英]c# System.InvalidCastException when passing datatable to stored procedure

我在MS SQL Server 2012 DB中定義了UDT,並在數據庫的存儲過程中使用了UDT。 我正在嘗試從c#程序調用存儲過程,但出現錯誤。 這是我的代碼:

這是我的UDT的定義:

CREATE TYPE [dbo].[udt_850File] AS TABLE(
    [strInbound850FromPharmacyFilename] [nvarchar](1000) NULL,
    [strSenderID_ISA06] [nvarchar](15) NOT NULL,
    [strReceiverID_ISA08] [nvarchar](15) NOT NULL,
    [strInterchangeControlVersion_ISA12] [nvarchar](5) NOT NULL,
    [strInterchangeControlNumber_ISA13] [nvarchar](9) NOT NULL,
    [chElementDelimiter] [nchar](1) NOT NULL,
    [chComponentElementDelimiter] [nchar](1) NOT NULL,
    [chSegmentTerminator] [nchar](1) NOT NULL,
    [intTransmissionDate_GS04] [int] NOT NULL,
    [strVersionRelease_GS08] [nvarchar](12) NOT NULL,
    [strTransSetControl_ST02] [nvarchar](9) NOT NULL,
    [strPONumber_BEG03] [nvarchar](22) NOT NULL,
    [intPODate_BEG05] [int] NOT NULL,
    [strWholesalerAccountNum_N1BY04] [nvarchar](80) NOT NULL,
    [dtFileCreatedDateTime] [datetime] NOT NULL
)

這是我的存儲過程定義:

CREATE PROCEDURE [dbo].[ppisp_sp_850Files_Insert]
    @850FileData [dbo].[udt_850File] READONLY
AS
    BEGIN

        DECLARE @ReturnVal INT = 0

        MERGE INTO [dbo].[850Files] AS target
        USING @850FileData AS source
            ON source.[strInbound850FromPharmacyFilename] = target.[strInbound850FromPharmacyFilename]
            AND source.[strSenderID_ISA06] = target.[strSenderID_ISA06]
            AND source.[strReceiverID_ISA08] = target.[strReceiverID_ISA08]
            AND source.[strInterchangeControlVersion_ISA12] = target.[strInterchangeControlVersion_ISA12]
            AND source.[strInterchangeControlNumber_ISA13] = target.[strInterchangeControlNumber_ISA13]
            AND source.[chElementDelimiter] = target.[chElementDelimiter]
            AND source.[chComponentElementDelimiter] = target.[chComponentElementDelimiter]
            AND source.[chSegmentTerminator] = target.[chSegmentTerminator]
            AND source.[intTransmissionDate_GS04] = target.[intTransmissionDate_GS04]
            AND source.[strVersionRelease_GS08] = target.[strVersionRelease_GS08]
            AND source.[strTransSetControl_ST02] = target.[strTransSetControl_ST02]
            AND source.[strPONumber_BEG03] = target.[strPONumber_BEG03]
            AND source.[intPODate_BEG05] = target.[intPODate_BEG05]
            AND source.[strWholesalerAccountNum_N1BY04] = target.[strWholesalerAccountNum_N1BY04]
            AND source.[dtFileCreatedDateTime] = target.[dtFileCreatedDateTime]
        WHEN NOT MATCHED BY TARGET THEN
            INSERT ([strInbound850FromPharmacyFilename]
                    , [strSenderID_ISA06]
                    , [strReceiverID_ISA08]
                    , [strInterchangeControlVersion_ISA12]
                    , [strInterchangeControlNumber_ISA13]
                    , [chElementDelimiter]
                    , [chComponentElementDelimiter]
                    , [chSegmentTerminator]
                    , [intTransmissionDate_GS04]
                    , [strVersionRelease_GS08]
                    , [strTransSetControl_ST02]
                    , [strPONumber_BEG03]
                    , [intPODate_BEG05]
                    , [strWholesalerAccountNum_N1BY04]
                    , [dtFileCreatedDateTime])
            VALUES (source.[strInbound850FromPharmacyFilename]
                    , source.[strSenderID_ISA06]
                    , source.[strReceiverID_ISA08]
                    , source.[strInterchangeControlVersion_ISA12]
                    , source.[strInterchangeControlNumber_ISA13]
                    , source.[chElementDelimiter]
                    , source.[chComponentElementDelimiter]
                    , source.[chSegmentTerminator]
                    , source.[intTransmissionDate_GS04]
                    , source.[strVersionRelease_GS08]
                    , source.[strTransSetControl_ST02]
                    , source.[strPONumber_BEG03]
                    , source.[intPODate_BEG05]
                    , source.[strWholesalerAccountNum_N1BY04]
                    , source.[dtFileCreatedDateTime]);

            SET @ReturnVal = @@ROWCOUNT
    END

這是我的c#類文件,在其中定義我的數據表並用數據填充它:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;

namespace PP_ISP_File
{
    public class PP_ISP_File_Data 
    {
        public DataTable dt_Files_Info { get; set; }

        public PP_ISP_File_Data(string strFileDirectoryPath, int intFileType)
        {
            dt_Files_Info = new DataTable();
            dt_Files_Info.Columns.Add("strSenderID_ISA06", typeof(string));
            dt_Files_Info.Columns["strSenderID_ISA06"].DefaultValue = default(string);
            dt_Files_Info.Columns.Add("strReceiverID_ISA08", typeof(string));
            dt_Files_Info.Columns["strReceiverID_ISA08"].DefaultValue = default(string);
            dt_Files_Info.Columns.Add("strInterchangeControlVersion_ISA12", typeof(string));
            dt_Files_Info.Columns["strInterchangeControlVersion_ISA12"].DefaultValue = default(string);
            dt_Files_Info.Columns.Add("strInterchangeControlNumber_ISA13", typeof(string));
            dt_Files_Info.Columns["strInterchangeControlNumber_ISA13"].DefaultValue = default(string);
            dt_Files_Info.Columns.Add("chElementDelimiter", typeof(char));
            dt_Files_Info.Columns["chElementDelimiter"].DefaultValue = default(char);
            dt_Files_Info.Columns.Add("chComponentElementDelimiter", typeof(char));
            dt_Files_Info.Columns["chComponentElementDelimiter"].DefaultValue = default(char);
            dt_Files_Info.Columns.Add("chSegmentTerminator", typeof(char));
            dt_Files_Info.Columns["chSegmentTerminator"].DefaultValue = default(char);
            dt_Files_Info.Columns.Add("intTransmissionDate_GS04", typeof(int));
            dt_Files_Info.Columns["intTransmissionDate_GS04"].DefaultValue = -1;
            dt_Files_Info.Columns.Add("strVersionRelease_GS08", typeof(string));
            dt_Files_Info.Columns["strVersionRelease_GS08"].DefaultValue = default(string);
            dt_Files_Info.Columns.Add("strTransSetControl_ST02", typeof(string));
            dt_Files_Info.Columns["strTransSetControl_ST02"].DefaultValue = default(string);

            if(intFileType == 850)
            {
                dt_Files_Info.Columns.Add("strInbound850FromPharmacyFilename", typeof(string));
                dt_Files_Info.Columns["strInbound850FromPharmacyFilename"].DefaultValue = default(string);
                dt_Files_Info.Columns.Add("strPONumber_BEG03", typeof(string));
                dt_Files_Info.Columns["strPONumber_BEG03"].DefaultValue = default(string);
                dt_Files_Info.Columns.Add("intPODate_BEG05", typeof(int));
                dt_Files_Info.Columns["intPODate_BEG05"].DefaultValue = -1;
                dt_Files_Info.Columns.Add("strWholesalerAccountNum_N1BY04", typeof(string));
                dt_Files_Info.Columns["strWholesalerAccountNum_N1BY04"].DefaultValue = default(string);
            }
            else if(intFileType == 855)
            {
                dt_Files_Info.Columns.Add("strOutbound855ToPharmacyFilename", typeof(string));
                dt_Files_Info.Columns["strOutbound855ToPharmacyFilename"].DefaultValue = default(string);
                dt_Files_Info.Columns.Add("strPONumber_BAK03", typeof(string));
                dt_Files_Info.Columns["strPONumber_BAK03"].DefaultValue = default(string);
                dt_Files_Info.Columns.Add("intPODate_BAK04", typeof(int));
                dt_Files_Info.Columns["intPODate_BAK04"].DefaultValue = -1;
                dt_Files_Info.Columns.Add("strWholesalerAccountNum_N1ST04", typeof(string));
                dt_Files_Info.Columns["strWholesalerAccountNum_N1ST04"].DefaultValue = default(string);
            }

            dt_Files_Info.Columns.Add("dtFileCreatedDateTime", typeof(DateTime));
            dt_Files_Info.Columns["dtFileCreatedDateTime"].DefaultValue = default(DateTime);

            dt_Files_Info = GetFileDetails(strFileDirectoryPath, intFileType);
        }

       private DataTable GetFileDetails(string strFileDirectoryPath, int intFileType)
        {
            DataTable dtPP_ISP_Files_Return = dt_Files_Info.Clone();

            DirectoryInfo diDirectoryInfo = new DirectoryInfo(strFileDirectoryPath);

            if (diDirectoryInfo.Exists)
            {
                foreach (FileInfo fiFileInfo in diDirectoryInfo.GetFiles())
                {
                    if (fiFileInfo.Exists)
                    {
                        using (StreamReader srFile = new StreamReader(fiFileInfo.FullName))
                        {
                            string strFileData = System.IO.File.ReadAllText(fiFileInfo.FullName);
                            if (strFileData.Length >= 104)
                            {
                                DataRow dr = dtPP_ISP_Files_Return.NewRow();

                                char chElementDelimiter = default(char);
                                char chComponentElementDelimiter = default(char);
                                char chSegmentTerminator = default(char);

                                chElementDelimiter = Convert.ToChar(strFileData.Substring(3, 1));
                                dr["chElementDelimiter"] = chElementDelimiter;
                                chComponentElementDelimiter = Convert.ToChar(strFileData.Substring(104, 1));
                                dr["chComponentElementDelimiter"] = chComponentElementDelimiter;
                                chSegmentTerminator = Convert.ToChar(strFileData.Substring(105, 1));
                                dr["chSegmentTerminator"] = chSegmentTerminator;
                                dr["dtFileCreatedDateTime"] = File.GetCreationTime(strFileDirectoryPath);

                                string[] arrFileLines = strFileData.Split(Convert.ToChar(chSegmentTerminator));

                                for (int i = 0; i <= arrFileLines.Length - 1; i++)
                                {
                                    string[] arrLineData = arrFileLines[i].Split(Convert.ToChar(chElementDelimiter));
                                    string strLineQualifier = arrLineData[0].Trim();

                                    switch (strLineQualifier)
                                    {
                                        case "ISA":
                                            dr["strSenderID_ISA06"] = arrLineData[6].Trim();
                                            dr["strReceiverID_ISA08"] = arrLineData[8].Trim();
                                            dr["strInterchangeControlVersion_ISA12"] = arrLineData[12].Trim();
                                            dr["strInterchangeControlNumber_ISA13"] = arrLineData[13].Trim();
                                            break;
                                        case "GS":
                                            dr["intTransmissionDate_GS04"] = Convert.ToInt32(arrLineData[4].Trim());
                                            dr["strVersionRelease_GS08"] = arrLineData[8].Trim();
                                            break;
                                        case "ST":
                                            dr["strTransSetControl_ST02"] = arrLineData[2].Trim();
                                            break;
                                        case "BEG":
                                            dr["strInbound850FromPharmacyFilename"] = fiFileInfo.Name;                                            
                                            dr["strPONumber_BEG03"] = arrLineData[3].Trim();
                                            dr["intPODate_BEG05"] = Convert.ToInt32(arrLineData[5].Trim());
                                            break;
                                        case "BAK":
                                            dr["strOutbound855ToPharmacyFilename"] = fiFileInfo.Name;
                                            dr["strPONumber_BAK03"] = arrLineData[3].Trim();
                                            dr["intPODate_BAK04"] = Convert.ToInt32(arrLineData[4].Trim());
                                            break;
                                        case "N1":
                                            if(arrLineData[1].Trim() == "BY")
                                            {
                                                dr["strWholesalerAccountNum_N1BY04"] = arrLineData[4].Trim();
                                                dtPP_ISP_Files_Return.Rows.Add(dr);
                                            }
                                            else if (arrLineData[1].Trim() == "ST")
                                            {
                                                dr["strWholesalerAccountNum_N1ST04"] = arrLineData[4].Trim();
                                                dtPP_ISP_Files_Return.Rows.Add(dr);
                                            }
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return dtPP_ISP_Files_Return;
        }
    }
}

最后,這是我的代碼,在該代碼中我初始化數據表,然后嘗試將其傳遞給數據庫中的存儲過程:

using (SqlCommand cmd = new SqlCommand(strSPName, con))
{
    PP_ISP_File_Data dtFileInfo = new PP_ISP_File_Data(strWatchPath, intFileType);

    cmd.CommandText = strSPName;
    cmd.CommandType = System.Data.CommandType.StoredProcedure;

    SqlParameter spFilenames = new SqlParameter("@850FileData", SqlDbType.Structured);
    spFilenames.TypeName = "dbo.udt_850File";
    spFilenames.Value = dtFileInfo;

    cmd.Parameters.Add(spFilenames);

    SqlParameter returnParameter = new SqlParameter("@ReturnVal", SqlDbType.Int);
    returnParameter.Direction = ParameterDirection.ReturnValue;

    cmd.Parameters.Add(returnParameter);

    con.Open();
    cmd.ExecuteNonQuery();
    int result = Convert.ToInt16(returnParameter.Value);
}

運行我的代碼給我這個錯誤:

System.InvalidCastException:'無法將參數值從PP_ISP_File_Data轉換為IEnumerable`1。

我有一個懷疑,因為我在類文件中聲明了數據表,所以在將其傳遞給存儲過程時沒有得到它需要能夠枚舉的東西,但是我不知道該如何糾正。 有人可以指出正確的方向來解決此問題嗎? 提前致謝。

實際上,您需要將數據表作為參數傳遞給存儲過程,以使其用作UDT,但現在您正在傳遞類的整個對象,該對象將無法工作。

因此,更改以下行:

spFilenames.Value = dtFileInfo;

至:

spFilenames.Value = dtFileInfo.dt_Files_Info;

從MSDN

System.Data.SqlClient支持從DataTableDbDataReaderIEnumerable \\ SqlDataRecord對象填充表值參數。

另請參閱將表值參數傳遞給存儲過程

您可以查看以下帖子以了解更多信息:

https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql/table-valued-parameters

https://visualstudiomagazine.com/articles/2015/06/01/table-valued-parameters.aspx

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM