c# – 如何在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 Server错误.

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

附: 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)

对于varchar和nvarchar,IsFixedSize返回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没有任何用处可以覆盖或挂钩. …

转载注明原文:c# – 如何在Linq To SQL中强制varchar长度 - 代码日志