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

时间:2015-03-11 08:39:32

标签: 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);
}

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

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

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

P.S。 nvarchar(4000)存在同样的问题。

1 个答案:

答案 0 :(得分:1)

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

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

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为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没有任何用处来覆盖或挂钩进入......