为什么我的 ADO.NET 查询不会 运行 单次执行,但它们会 运行 单独执行?

Why my ADO.NET queries does not run in single execution but they will run in seperate executions?

关于一个问题及其相关 ,我正在尝试使用 SQL 查询和 运行 对数据的连接查询创建一个新的 table 类型属于这种 table 类型。

我将两个查询放在同一个脚本中,即 create typeselect 但它不起作用。我的查询如下(全部代码带在问题末尾):

IF TYPE_ID(N'BranchMappingType') IS NULL 
CREATE TYPE BranchMappingType As Table 
(COL_ServerID int, 
COL_ServerSchema Common._SMALL_, 
COL_TableName Common._SMALL_, 
COL_BranchNo Common._SMALL_, 
COL_BranchSchema Common._SMALL_ ); 

SELECT [VMA_BranchID] FROM [VIP].[VipMapping] 
JOIN @TVP ON 
VMA_ServerID=COL_ServerID  AND 
VMA_ServerSchema=COL_ServerSchema  AND 
VMA_TableName=COL_TableName  AND 
VMA_BranchNo=COL_BranchNo  AND 
VMA_BranchSchema=COL_BranchSchema;

我将使用 SqlDataReader.ExecuteReader 执行我的查询,但它会抛出异常:

Column, parameter, or variable @TVP. : Cannot find data type BranchMappingType.

但是当我 运行 查询的第一部分时,即 IF TYPE_ID(...) ... CREATE TYPE 它将毫无错误地执行并且 then 运行ning第二部分即 Select from ... join @TVP 完美运行。

似乎新创建的 table 类型无法识别,当我 运行 两个查询都单次执行 SqlDataReader.ExecuteReader 时。

我想知道是什么原因以及我在实施过程中是否犯了一些错误?我更喜欢 运行 一次性调用 SqlDataReader.ExecuteReader 方法的两个查询。

这里是完整的代码以便更好地检查:

List<int> keys = new List<int>();
if (foreignKeyInfoList == null || foreignKeyInfoList.Count == 0)
    return new StatusResponseKeysList { ErrorCode = ErrorCodes.ERROR_CODE_MINUS_019_NULL_OR_EMPTY_INPUT_ARGUMENT };
const string ID_FIELD = "VMA_BranchID";
const string STRUCTURED_DATA_TABLE_NAME = "@TVP";
const string COL1_SERVER_ID = "COL_ServerID";
const string COL2_SERVER_SCHEMA = "COL_ServerSchema";
const string COL3_TABLE_NAME = "COL_TableName";
const string COL4_BRANCH_NO = "COL_BranchNo";
const string COL5_BRANCH_SCHEMA = "COL_BranchSchema";
//const string COL6_TABLE_ID = "COL_TableID";
const string MAP1_SERVER_ID = "VMA_ServerID";
const string MAP2_SERVER_SCHEMA = "VMA_ServerSchema";
const string MAP3_TABLE_NAME = "VMA_TableName";
const string MAP4_BRANCH_NO = "VMA_BranchNo";
const string MAP5_BRANCH_SCHEMA = "VMA_BranchSchema";
const string TYPE_NAME = "BranchMappingType";
//const string MAP6_TABLE_ID = "VMA_TableID";
string sqlQuery = $"IF TYPE_ID(N'{TYPE_NAME}') IS NULL" + " " +
                   $"CREATE TYPE {TYPE_NAME} As Table" + " " +
                   $"({COL1_SERVER_ID} int," + " " +
                   $"{COL2_SERVER_SCHEMA} Common._SMALL_," + " " +
                   $"{COL3_TABLE_NAME} Common._SMALL_," + " " +
                   $"{COL4_BRANCH_NO} Common._SMALL_," + " " +
                   $"{COL5_BRANCH_SCHEMA} Common._SMALL_" + " " +
                   $"); ";

sqlQuery += $"SELECT [{ID_FIELD}] " +
                  $"FROM {Settings.VIP_MAPPING_TABLE} " +
                  $"JOIN {STRUCTURED_DATA_TABLE_NAME} ON " +
                  $"{MAP1_SERVER_ID}={COL1_SERVER_ID} " +
                  $" AND {MAP2_SERVER_SCHEMA}={COL2_SERVER_SCHEMA} " +
                  $" AND {MAP3_TABLE_NAME}={COL3_TABLE_NAME} " +
                  $" AND {MAP4_BRANCH_NO}={COL4_BRANCH_NO} " +
                  $" AND {MAP5_BRANCH_SCHEMA}={COL5_BRANCH_SCHEMA} ";// +
                                                                     //$" AND {MAP6_TABLE_ID}={COL6_TABLE_ID}"; 
DataTable dataTable = new DataTable(TYPE_NAME);
dataTable.Columns.Add(COL1_SERVER_ID, typeof(int));
dataTable.Columns.Add(COL2_SERVER_SCHEMA, typeof(string));
dataTable.Columns.Add(COL3_TABLE_NAME, typeof(string));
dataTable.Columns.Add(COL4_BRANCH_NO, typeof(string));
dataTable.Columns.Add(COL5_BRANCH_SCHEMA, typeof(string));
//dataTable.Columns.Add(COL6_TABLE_ID, typeof(int));

for (int i = 0; i < foreignKeyInfoList.Count; i++)
{
    ForeignKeyLookupModelInBranchSide oneKeySet = foreignKeyInfoList[i];
    DataRow row = dataTable.NewRow();
    row[COL1_SERVER_ID] = Int32.Parse(oneKeySet.ServerID);
    row[COL2_SERVER_SCHEMA] = oneKeySet.ServerSchema;
    row[COL3_TABLE_NAME] = oneKeySet.TableName;
    row[COL4_BRANCH_NO] = oneKeySet.BranchNo;
    row[COL5_BRANCH_SCHEMA] = oneKeySet.BranchSchema;
    dataTable.Rows.Add(row);
}

try
{
    using (SqlConnection sqlConnection = new SqlConnection(Settings.connectionString))
    {
        SqlCommand command = new SqlCommand(sqlQuery, sqlConnection);
        SqlParameter p = command.Parameters.Add(STRUCTURED_DATA_TABLE_NAME, SqlDbType.Structured);
        p.Value = dataTable;
        p.TypeName = TYPE_NAME;
        sqlConnection.Open();
        SqlDataReader reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            while (reader.Read())
            {
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    keys.Add(reader.GetInt32(i));
                }
            }
        }
        else
        {
        }
        sqlConnection.Close();
    }
    return new StatusResponseKeysList
    {
        keysList = keys,
        ErrorCode = ErrorCodes.ERROR_CODE_MINUS_019_NULL_OR_EMPTY_INPUT_ARGUMENT
    };
}
catch (Exception e) 
{
    //Exception caught here !!!!!!!: 
    //"Column, parameter, or variable @TVP. : Cannot find data type BranchMappingType."
    if (e.GetType() == typeof(SqlException))
    {
        //this is a db error
        return new StatusResponseKeysList
        {
            ErrorCode = ErrorCodes.ERROR_CODE_MINUS_014_DATABASE_EXCEPTION
        };
    }
    else
    {
        //other types of erros (not a DB-error)
        return new StatusResponseKeysList
        {
            ErrorCode = ErrorCodes.ERROR_CODE_MINUS_001_COMMON_ERROR
        };

    }
}

在执行使用该类型的参数化查询之前,table 类型必须存在。原因是数据库引擎首先在 tempdb 中创建一个内部 table,匹配在服务器 上定义的 table 类型,然后批处理执行 。然后它使用 API 提供的结构化参数值和元数据将 TVP 值批量插入到 tempdb 中。只有在加载 table 后批处理才会执行,它可以在其中使用 TVP 值。

这意味着不能创建 table 类型并在使用该类型作为参数的同一批次中使用它。