【问题标题】:Entity Framework Core 3.1 stored procedure optional parameters not workingEntity Framework Core 3.1 存储过程可选参数不起作用
【发布时间】:2020-12-11 07:55:19
【问题描述】:

[已解决](见结尾)

我大部分时间都在寻找一个没有运气的解决方案。

  • EF Core 3.1
  • Visual Studio 2019
  • SQL Server 2017
  • .Net Core 3.1

我无法找到一种解决方案,可以使用可选参数从 .Net Core 3.1 调用存储过程。我已经阅读了几十篇从 SO 到博客的文章,但没有任何效果。

这是我的 C# 代码,用于调用存储过程的方法,并尽一切努力使其工作:

public List<BudgetWorkflowStatusByDepartment> GetBudgetWorkflowStatusByDepartment(int? companyId, int? departmentId, int? locationId, int? sublocationId)
{
        //var compId = new SqlParameter("@CompanyId", companyId);
        //compId.Value = (object)companyId ?? SqlInt32.Null;

        //var deptId = new SqlParameter("@DepartmentId", departmentId);
        //deptId.Value = (object)departmentId ?? SqlInt32.Null;

        //var locId = new SqlParameter("@LocationId", locationId);
        //locId.Value = (object)locationId ?? SqlInt32.Null;

        //var subId = new SqlParameter("@SubLocationId", sublocationId);
        //subId.Value = (object)sublocationId ?? SqlInt32.Null;

        var compId = new SqlParameter("@CompanyID", companyId);
        compId.Value = (object)companyId ?? DBNull.Value;

        var deptId = new SqlParameter("@DepartmentID", departmentId);
        deptId.Value = (object)departmentId ?? DBNull.Value;

        var locId = new SqlParameter("@LocationID", locationId);
        locId.Value = (object)locationId ?? DBNull.Value;

        var subId = new SqlParameter("@SubLocationID", sublocationId);
        subId.Value = (object)sublocationId ?? DBNull.Value;

        //var result = context.BudgetWorkflowStatusByDepartment
        //    .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID, @DepartmentID, @LocationID, @SubLocationID", compId, deptId, locId, subId).ToList();

        //var result = context.BudgetWorkflowStatusByDepartment
        //    .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment {0}, {1}, {2}, {3}", companyId, departmentId, locationId, companyId).ToList();

        // Error Must declare the scalar variable "@CompanyID".
        //var result = context.BudgetWorkflowStatusByDepartment
        //    .FromSqlRaw($"EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID={compId}, @DepartmentID={deptId}, @LocationID={locId}, @SubLocationID={subId}").ToList();

        // Error Must declare the scalar variable "@CompanyID".
        var result = context.BudgetWorkflowStatusByDepartment
            .FromSqlRaw($"EXEC mis.BudgetWorkflowStatusByDepartment {compId}, {deptId}, {locId}, {subId}").ToList();

        //var result = context.BudgetWorkflowStatusByDepartment
        //        .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID={compId}, @DepartmentID={deptId}, @LocationID={locId}, @SubLocationID={subId}").ToList();

        return result;
}

这些尝试都不起作用。错误范围为:

数据为空。不能对 Null 值调用此方法或属性。

...到...

必须声明标量变量“@compId”。

...当我刚刚尝试了一些很可能只是不正确的东西以拼命尝试让它工作时出现的一些其他错误。

这是存储过程本身的签名,表明所有参数都可以为空。

ALTER PROCEDURE [mis].[BudgetWorkflowStatusByDepartment] 
    (@CompanyID int = null,
     @DepartmentID int = null,
     @LocationID int = null,
     @SubLocationID int = null)

令人沮丧的是,这个存储过程在 SQL Server 和 LinqPad 中无论有无参数都可以工作。它在我的代码中仅适用于所有参数,但如果有任何参数为空,则会引发错误。

感谢任何有关如何让函数使用可选参数的见解。

编辑:2020 年 8 月 24 日

根据新的建议,我尝试了它们,但由于某种原因它们仍然不起作用。

我已经在 SSMS 中使用所有四个参数直接测试了存储过程,并且它可以工作。然后我一个一个地删除了最后的每个参数,并在每个参数都被删除时对其进行了测试,它可以返回正确的数据。

当我使用 Api 和对该方法的服务调用进行相同的测试时,四个参数有效,三个参数有效,但是 2 个参数,1 个参数和没有参数,不工作!我不明白为什么不。

这是我的新尝试:


            /// New attempts as of: 8/24/2020
            // Error Data is Null. This method or property cannot be called on Null values.
            //var compId = new SqlParameter("@CompanyID", companyId);
            //compId.Value = (object)companyId ?? DBNull.Value;

            //var deptId = new SqlParameter("@DepartmentID", departmentId);
            //deptId.Value = (object)departmentId ?? DBNull.Value;

            //var locId = new SqlParameter("@LocationID", locationId);
            //locId.Value = (object)locationId ?? DBNull.Value;

            //var subId = new SqlParameter("@SubLocationID", sublocationId);
            //subId.Value = (object)sublocationId ?? DBNull.Value;

            //var result = context.BudgetWorkflowStatusByDepartment
            //        .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment {compId}, {deptId}, {locId}, {subId}").ToList();

            // Error Data is Null. This method or property cannot be called on Null values.
            
            //var result = context.BudgetWorkflowStatusByDepartment
            //        .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment {companyId}, {departmentId}, {locationId}, {sublocationId}").ToList();


            //var compId = new SqlParameter("@CompanyID", companyId) { IsNullable = true };
            //compId.Value = (object)companyId ?? DBNull.Value;

            //var deptId = new SqlParameter("@DepartmentID", departmentId) { IsNullable = true };
            //deptId.Value = (object)departmentId ?? DBNull.Value;

            //var locId = new SqlParameter("@LocationID", locationId) { IsNullable = true };
            //locId.Value = (object)locationId ?? DBNull.Value;

            //var subId = new SqlParameter("@SubLocationID", sublocationId) { IsNullable = true };
            //subId.Value = (object)sublocationId ?? DBNull.Value;

            //// Error Data is Null. This method or property cannot be called on Null values.
            //var result = context.BudgetWorkflowStatusByDepartment
            //                    .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID = @CompanyID, @DepartmentID = @DepartmentID, @LocationID = @LocationID, @SubLocationID = @SubLocationID", compId, deptId, locId, subId)
            //                    .ToList();

            var compId = new SqlParameter("@CompanyID", companyId) { IsNullable = true };
            compId.Value = (object)companyId ?? DBNull.Value;

            var deptId = new SqlParameter("@DepartmentID", departmentId) { IsNullable = true };
            deptId.Value = (object)departmentId ?? DBNull.Value;

            var locId = new SqlParameter("@LocationID", locationId) { IsNullable = true };
            locId.Value = (object)locationId ?? DBNull.Value;

            var subId = new SqlParameter("@SubLocationID", sublocationId) { IsNullable = true };
            subId.Value = (object)sublocationId ?? DBNull.Value;

            // Error Data is Null. This method or property cannot be called on Null values.
            var result = context.BudgetWorkflowStatusByDepartment
                                .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID, @DepartmentID, @LocationID, @SubLocationID", compId, deptId, locId, subId)
                                .ToList();

我认为我应该将此存储过程的 DbContext 属性设置作为附加信息包含在内。同样的模式用于另外两个存储过程,它们可以工作,但不需要可选参数。

        public DbSet<BudgetWorkflowStatusByDepartment> BudgetWorkflowStatusByDepartment { get; set; }

在 OnModelCreating() 方法中,我设置了 HasNoKey() 方法。

            modelBuilder.Entity<BudgetWorkflowStatusByDepartment>().HasNoKey();

感谢大家的建议。

我的解决方法是告诉 DBA 更改存储过程以一起删除所有参数,然后我将只对结果执行 .Where() 子句。

幸运的是,对于这个特殊的功能,它不会返回超过 200 行,但它会返回很多列,但这仍然不应该是繁重的。

解决原因

这是我的错。我有一些int 属性需要为可空整数。一旦我这样做了,它就起作用了,而且它似乎适用于大多数解决方案。

重要的是要注意那些可能为空的属性并使它们可以为空,这样你就不会成为我的问题的牺牲品,这需要一整天的时间来解决。


我认为,由于我正在经历所有这些我以前没有做过的尝试(使用带有 .Net Core 3.1 存储过程的可选参数),我会使用各种选项来记录我的结果以处理这个问题.

这些是关于从 .Net Core 3.1 执行存储过程时哪些有效和无效的一些选项。

对于这些示例,这将是 .Net Core 方法的签名。

public List<BudgetWorkflowStatusByDepartment> GetBudgetWorkflowStatusByDepartment
(int? companyId, int? departmentId, int? locationId, int? sublocationId)
{
...
}

所有参数都是可选的。以下示例将是您可以在此方法中使用的代码。

这是存储过程的签名。

ALTER procedure mis.BudgetWorkflowStatusByDepartment_Filtered (
      @CompanyID int = null
    , @DepartmentID int = null
    , @LocationID int = null
    , @SubLocationID int = null
)

工作示例

以下示例演示如何使用FromSqlRawFromSqlInterpolated 方法来执行存储过程。

FromSqlRaw 方法

此示例仅创建 SqlParameter 对象并将值设置为传入值或 DbNull。这很重要,因为null 在这种情况下不起作用。 (请参阅下面的非工作示例)

// Works
var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
.FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID, @DepartmentID, @LocationID, @SubLocationID", compId, deptId, locId, subId).ToList();


以下通过包含SqlParameter 对象的IsNullable=true 属性来工作。

// Works
var compId = new SqlParameter("@CompanyID", companyId) { IsNullable = true };
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId) { IsNullable = true };
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId) { IsNullable = true };
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId) { IsNullable = true };
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
        .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID = @CompanyID, @DepartmentID = @DepartmentID, @LocationID = @LocationID, @SubLocationID = @SubLocationID", compId, deptId, locId, subId)
        .ToList();

以下与上面类似,但语法略简写。

// Works
var compId = new SqlParameter("@CompanyID", companyId) { IsNullable = true };
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId) { IsNullable = true };
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId) { IsNullable = true };
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId) { IsNullable = true };
subId.Value = (object)sublocationId ?? DBNull.Value;

// Works
var result = context.BudgetWorkflowStatusByDepartment
        .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID, @DepartmentID, @LocationID, @SubLocationID", compId, deptId, locId, subId)
        .ToList();

FromSqlInterpolated

以下内容有效,因为它使用.FromSqlInterpolated() 方法,然后占位符语法将有效。

// Works
var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
    .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID={compId}, @DepartmentID={deptId}, @LocationID={locId}, @SubLocationID={subId}").ToList();

以下与上面类似,但使用了略短的语法。

// Works
var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
    .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment_Filtered {compId}, {deptId}, {locId}, {subId}").ToList();

以下是终极的速记语法。使用插值方法,可以直接使用传入的变量,而不必创建SqlParameter对象。

// Works
var result = context.BudgetWorkflowStatusByDepartment
    .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment_Filtered {companyId}, {departmentId}, {locationId}, {sublocationId}").ToList();

非工作示例

以下代码返回一个空数组,这是不正确的。代码的这种参数化只能与“插值”的Sql方法一起使用。


// Returns empty array
var result = context.BudgetWorkflowStatusByDepartment
.FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment_Filtered {0}, {1}, {2}, {3}", companyId, departmentId, locationId, companyId).ToList();

结果 - 一个空数组,这是不正确的:

[]

以下方法在FromSqlRaw 方法的语法中不正确。字符串中的参数要使用插值,但该语法的方法是错误的。

// Error Must declare the scalar variable "@CompanyID".
var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
.FromSqlRaw($"EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID={compId}, @DepartmentID={deptId}, @LocationID={locId}, @SubLocationID={subId}").ToList();

错误:

Must declare the scalar variable "@CompanyID".

以下也是错误的。字符串中的参数不能以这种方式填充。

// Error Must declare the scalar variable "@CompanyID".
var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? DBNull.Value;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? DBNull.Value;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? DBNull.Value;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? DBNull.Value;

var result = context.BudgetWorkflowStatusByDepartment
.FromSqlRaw($"EXEC mis.BudgetWorkflowStatusByDepartment_Filtered {compId}, {deptId}, {locId}, {subId}").ToList();

错误:

Must declare the scalar variable "@CompanyID".

最后,这也不起作用,因为?? 运算符将空值设置为null 而不是DbNull.Value


var compId = new SqlParameter("@CompanyID", companyId);
compId.Value = (object)companyId ?? null;

var deptId = new SqlParameter("@DepartmentID", departmentId);
deptId.Value = (object)departmentId ?? null;

var locId = new SqlParameter("@LocationID", locationId);
locId.Value = (object)locationId ?? null;

var subId = new SqlParameter("@SubLocationID", sublocationId);
subId.Value = (object)sublocationId ?? null;

var result = context.BudgetWorkflowStatusByDepartment
.FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment_Filtered @CompanyID, @DepartmentID, @LocationID, @SubLocationID", compId, deptId, locId, subId).ToList();

错误:

The parameterized query '(@CompanyID nvarchar(4000),@DepartmentID nvarchar(4000),@Locatio' expects the parameter '@CompanyID', which was not supplied.

【问题讨论】:

  • 这能回答你的问题吗? Optional Parameters with EF Core FromSql
  • @CoolBots 不幸的是没有。我其实也试过了。我会继续寻找。
  • 我刚刚在您的注释代码中看到了这一点 - 我建议通过您帖子中的 EDIT 将其放在前面和中心 - 否则,您将被标记为重复。你可以试试 SQL Profiler,看看会发生什么,看看如果你在 SSMS 中执行那个确切的命令会出现什么错误?
  • 我还要仔细检查一下,以防万一,命名参数似乎是可选参数存储过程执行的要求。您注释代码中的格式与类似问题中的格式有点不同 - 一个是插值字符串 - 试试看?
  • 对不起,把什么放在前面和中间?我也确实使用了 SQL Profiler,它返回了这个:exec sp_executesql N'EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID=@CompanyID, @DepartmentID=@DepartmentID, @LocationID=@LocationID, @SubLocationID=@SubLocationID ',N'@CompanyID nvarchar(4000),@DepartmentID nvarchar(4000),@LocationID nvarchar(4000),@SubLocationID nvarchar(4000)',@CompanyID=NULL,@DepartmentID=NULL,@LocationID=NULL,@SubLocationID=NULL。不知道为什么 nvarchar(4000) 在那里,但它是。

标签: c# sql-server stored-procedures entity-framework-core optional-parameters


【解决方案1】:

我刚刚重新创建了一个类似的设置(您拥有的所有内容的相同版本),以下单行适用于我:

public List<BudgetWorkflowStatusByDepartment> GetBudgetWorkflowStatusByDepartment(int? companyId, int? departmentId, int? locationId, int? sublocationId)
     => context.BudgetWorkflowStatusByDepartment
               .FromSqlInterpolated($"EXEC mis.BudgetWorkflowStatusByDepartment {companyId}, {departmentId}, {locationId}, {subLocationId}").ToList();

注意,由于我使用的是.FromSqlInterpolated() 调用,因此无需创建SqlParameters - int? 可以直接传入,因为这是一个安全调用,根据docs,并且null 值得到了正确处理。

我看到您也尝试了此调用,但您似乎将 SqlParameters 传递给它,而不是数据本身 - 试试我的版本?

经过进一步测试,我通过将SqlParameter.IsNullable 属性设置为true,使您的版本可以正常工作,并稍作修改:

public List<BudgetWorkflowStatusByDepartment> GetBudgetWorkflowStatusByDepartment(int? companyId, int? departmentId, int? locationId, int? sublocationId)
{
    var compId = new SqlParameter("@CompanyID", companyId) { IsNullable = true };
    compId.Value = (object)companyId ?? DBNull.Value;

    var deptId = new SqlParameter("@DepartmentID", departmentId) { IsNullable = true };
    deptId.Value = (object)departmentId ?? DBNull.Value;

    var locId = new SqlParameter("@LocationID", locationId) { IsNullable = true };
    locId.Value = (object)locationId ?? DBNull.Value;

    var subId = new SqlParameter("@SubLocationID", sublocationId) { IsNullable = true };
    subId.Value = (object)sublocationId ?? DBNull.Value;


    var result = context.BudgetWorkflowStatusByDepartment
                        .FromSqlRaw("EXEC mis.BudgetWorkflowStatusByDepartment @CompanyID = @CompanyID, @DepartmentID = @DepartmentID, @LocationID = @LocationID, @SubLocationID = @SubLocationID", compId, deptId, locId, subId)
                        .ToList();

    return result;
}

任你选择 - 我个人喜欢单线 :)

【讨论】:

  • 不幸的是,这些建议都不起作用。我不确定问题是什么,但我会继续寻找。我收到相同的错误消息:Data is Null. This method or property cannot be called on Null values.
  • 这真的很奇怪 - 我实际上重新创建了你的设置,它工作正常 - 然后还有其他东西在起作用,不是你帖子的一部分,但会影响结果。你有最新版本的 EF Core 吗?
  • 我发现了问题。模型是我的错。返回类型的类的一些int 属性需要是可为空的int,但不是。一旦我这样做了,它就起作用了。所以我正在使用你的插值解决方案。我将使用修复声明更新我的帖子。
【解决方案2】:

我发现使用 dotnetcore 获取命名参数(以及可选参数)的唯一方法是使用以下方法:

_context.Database.ExecuteSqlRaw("EXEC mysproc @param1={0}, @param2={1}"
        ,param1
        ,param2);

... 其中 param1 和 param2 是 Microsoft.Data.SqlClient.SqlParameter 类型(这很重要,因为我发现 System.Data.SqlClient.SqlParamater 类型不会产生编译错误但会导致混淆运行时异常)。

虽然这始终有效,即使使用输出参数(在参数占位符后添加“out”),当您的代码可能通过不同的参数集提供不同的结果时,这是一种非常不灵活的创建语句的方式。我的一个用例有 23 个我可能提供的参数,其中只有三个是必需的。硬编码 ExecuteSqlRaw 语句不是一种选择。

我已经想出了一个有用的方法,我在控制器、页面等中使用了 DbContext _context:

private void ExecuteStoredProcedure(
        string StoredProcedureName
        ,List<SqlParameter> parameters)
{           
    StringBuilder stringBuilder = null;
    int paramNum = 0;

    // Build the T-SQL statement to enable named paramaters
    foreach (SqlParameter param in parameters)
    {
        string direction = param.Direction == ParameterDirection.Output ? " out" : "";
        if (stringBuilder == null)
        {                    
            stringBuilder = new StringBuilder(string.Format(CultureInfo.CurrentCulture
                    , "EXEC {0} {1}={{{2}}}{3}"
                    , StoredProcedureName
                    , param.ParameterName
                    , paramNum++
                    , direction));
        }
        else
        {
            stringBuilder.Append(string.Format(CultureInfo.CurrentCulture
                , ",{0}={{{1}}}{2}"
                , param.ParameterName
                , paramNum++
                , direction));
        }
    }

    try
    {
        _context.Database.ExecuteSqlRaw(
            stringBuilder.ToString()
            ,parameters.ToArray());
    }
    catch (Exception ex)
    {
         throw;
    }
}

该方法采用任意顺序的 SqlParameters 列表。请注意,列表在传递给 ExecuteSqlRaw 之前会转换为 SqlParamater 数组。从技术上讲,它不是“参数数组”,但我还没有看到它失败。您可能还想将 DBContext 或 DatabaseFacade 传递给该方法。

我通常按以下方式构造参数列表。 ParameterName 属性必须与它将提供的存储过程参数的名称相匹配。我已经排除了包含/排除参数的任何逻辑。

List<SqlParameter> parameters = new List<SqlParameter>();

parameters.Add(new SqlParameter()
    {
        ParameterName = "@MyOutputParam",
        DbType = System.Data.DbType.Int64,
        Direction = System.Data.ParameterDirection.Output
    });

parameters.Add(new SqlParameter()
    {
        ParameterName = "@RequiredButNullableUnicodeString",
        DbType = System.Data.DbType.String,
        Size = 50,
        Value = DBNull.Value
    });

parameters.Add(new SqlParameter()
   {
        ParameterName = "@SomeVarchar",
        DbType = System.Data.DbType.AnsiString,
        Size = 100,
        Value = "some value"
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 2019-11-05
    • 2020-03-05
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多