2015-03-11 23 views
8

Kiedy w LINQ to SQL używam funkcji zdefiniowanej przez użytkownika jak toJak mogę zmusić długość varchar w 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); 
} 

otrzymany zapytań zawsze zawiera VARCHAR (8000) jako typ parametru.

Muszę zmienić typ parametru funkcji, aby uniknąć błędu SQL Servera.

Czy mogę zmusić Linq do SQL, aby nie ignorował długości, którą przechodzę?

P.S. Jest taki sam problem z nvarchar (4000).

+0

Czy widzisz jakąkolwiek różnicę jeśli podasz nazwę parametru w funkcji (np 'FindA [parametr (Name = @" słowa kluczowe ", DbType = @" varchar (100) ")] słowa kluczowe łańcucha)')? –

Odpowiedz

1

Przeglądając kod decompiled to naprawdę nie wygląda to zwraca uwagę na tego atrybutu podczas tworzenia zapytania i tak naprawdę nie zobaczyć ścieżkę, która pozwoli Ci ustawić go

Wygląda to być plik który określa wielkość parametru użyć

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

tej części wewnątrz InitializeParameter inicjuje wielkości

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

Następnie po execute ścieżka jest po prostu ustawiona na 8000 i 4000 dla varchars dla nvarchars i naprawdę nie zawsze patrzeć na tego atrybutu

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

tym stwierdzeniem

if (!isInputParameter || declaredType.IsFixedSize) 

IsFixedSize zwraca false i varchar nvarchar, który można zobaczyć tutaj:

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

Źródło I przeszło przez kod podczas wykonywania funkcji, aby obejrzeć jej wykonanie pa th ... Wydaje się, że nie ma żadnych przydatnych haczyków do modyfikacji przed wykonaniem ... SqlProvider nie ma nic użytecznego do nadpisania lub podpięcia się ...