2015-03-11 12 views
8

Quando in LINQ to SQL che uso funzione definita dall'utente come questoCome posso forzare la lunghezza varchar in 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); 
} 

la query risultante contiene sempre varchar (8000) come un tipo di parametro.

Quindi devo modificare il tipo di parametro della funzione per evitare l'errore di SQL Server.

Posso forzare Linq To SQL a non ignorare la lunghezza che passo?

P.S. C'è lo stesso problema con nvarchar (4000).

+0

Vedete qualche differenza se specificate il nome del parametro nella funzione (es 'FindA [Parametro (Nome = @" parole chiave ", DbType = @" varchar (100) ")] stringa di parole chiave)')? –

risposta

1

Guardando attraverso il codice decompilato in realtà non sembra che presta attenzione a questo attributo quando compone la query e non ho davvero vedere un percorso che avrebbe permesso lo si imposta

Questo sembra essere il file che determina la dimensione parametro da utilizzare

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

Questa parte interna InitializeParameter inizializza il formato

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

Poi seguendo il percorso è solo eseguire impostata su 8000 per VARCHAR e 4000 per nvarchars e in realtà non sempre guarda quell'attributo

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

questa dichiarazione

if (!isInputParameter || declaredType.IsFixedSize) 

IsFixedSize restituisce false per varchar e nvarchar che potete vedere qui

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

fonte ho fatto un passo attraverso il codice durante l'esecuzione di una funzione così a guardare la sua pa esecuzione th ... Inoltre non sembra che ci siano dei ganci utili da modificare prima dell'esecuzione. Lo SqlProvider non ha nulla di utile da ignorare o agganciare in uno dei due ...