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

Ale*_*rev 8 c# sql-server linq-to-sql

在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);
}
Run Code Online (Sandbox Code Playgroud)

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

所以我必须更改函数的参数类型以避免SQL Server错误.

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

PS nvarchar(4000)也存在同样的问题.

Sha*_*lle 2

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

这看起来是确定要使用的参数大小的文件

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

InitializeParameter 内的这部分初始化 Size

 int? determinedSize = DetermineParameterSize(sqlType, parameter);
 if (determinedSize.HasValue) {
        parameter.Size = determinedSize.Value;
 }
Run Code Online (Sandbox Code Playgroud)

然后执行路径只是将 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;
}
Run Code Online (Sandbox Code Playgroud)

这个说法

if (!isInputParameter || declaredType.IsFixedSize)
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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