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

How can I force varchar length in 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);
}

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

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

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

P.S。 nvarchar(4000) 也有同样的问题。

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

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

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;
 }

然后执行路径后面的 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 returns 对于 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 没有任何有用的东西可以覆盖或挂钩....