如何在 Linq To SQL 中强制 varchar 长度



在Linq To SQL中,我使用这样的用户定义函数

[Function(Name = "udf_find_a", IsComposable = true)]
public IQueryable<A> FindA([Parameter(DbType = "varchar(100)")] string keywords)
{
    return CreateMethodCallQuery<A>(this, ((MethodInfo) (MethodBase.GetCurrentMethod())), keywords);
}

生成的查询始终包含 varchar(8000) 作为参数类型。

所以我必须更改函数的参数类型以避免SQL服务器错误。

我可以强制 Linq To SQL 不忽略我传递的长度吗?

附言nvarchar(4000) 也有同样的问题。

浏览反编译的代码,在编写查询时看起来并没有真正关注该属性,而且我真的没有看到可以让您设置它的路径

这似乎是确定要使用的参数大小的文件

https://github.com/Microsoft/referencesource/blob/master/System.Data.Linq/SqlClient/SqlTypeSystemProvider.cs

初始化

参数中的这部分初始化大小

 int? determinedSize = DetermineParameterSize(sqlType, parameter);
 if (determinedSize.HasValue) {
        parameter.Size = determinedSize.Value;
 }

然后遵循执行路径只是设置为 varchars 的 8000 和 nvarchars 的 4000,并且实际上从未查看过该属性

 internal virtual int? DetermineParameterSize(SqlType declaredType, DbParameter parameter) {
        // Output parameters and input-parameters of a fixed-size should be specifically set if value fits.
        bool isInputParameter = parameter.Direction == ParameterDirection.Input;
        if (!isInputParameter || declaredType.IsFixedSize) {
            if (declaredType.Size.HasValue && parameter.Size <= declaredType.Size || declaredType.IsLargeType) {
                return declaredType.Size.Value;
            }
        }
        // Preserve existing provider & server-driven behaviour for all other cases.
        return null;
    }
    protected int? GetLargestDeclarableSize(SqlType declaredType) {
            switch (declaredType.SqlDbType) {
            case SqlDbType.Image:
            case SqlDbType.Binary:
            case SqlDbType.VarChar:
                return 8000;
            case SqlDbType.NVarChar:
                return 4000;
            default:
                return null;
        }
    }
    internal virtual int? DetermineParameterSize(SqlType declaredType, DbParameter parameter) {
    // Output parameters and input-parameters of a fixed-size should be specifically set if value fits.
    bool isInputParameter = parameter.Direction == ParameterDirection.Input;
    if (!isInputParameter || declaredType.IsFixedSize) {
        if (declaredType.Size.HasValue && parameter.Size <= declaredType.Size || declaredType.IsLargeType) {
            return declaredType.Size.Value;
        }
    }
    // Preserve existing provider & server-driven behaviour for all other cases.
    return null;
}

此声明

if (!isInputParameter || declaredType.IsFixedSize)

IsFixedSize 为 varchar 和 nvarchar 返回 false,您可以在此处看到

internal override bool IsFixedSize {
    get {
        switch (this.sqlDbType) {
            case SqlDbType.NText:
            case SqlDbType.Text:
            case SqlDbType.NVarChar:
            case SqlDbType.VarChar:
            case SqlDbType.Image:
            case SqlDbType.VarBinary:
            case SqlDbType.Xml:
                return false;
            default:
                return true;
        }
    }
}

我在执行函数时也逐步执行代码以观察其执行路径......在执行之前似乎也没有任何有用的钩子可以修改。SqlProvider 没有任何有用的东西可以覆盖或挂钩到其中。

最新更新