2017-06-01 4 views
0

Je suis nouveau dans Dapper et j'écris une requête qui tirera d'un schéma et d'une table fournis, ainsi que de l'ordre et du filtrage dynamiques. Dapper rendre les paramètres dynamiques très simple, cependant, je ne suis pas sûr de savoir comment faire cela avec des tables dans les clauses order by et where. Voici ma méthode ci-dessous, et je vois les problèmes avec injection SQL:Comment désinfecter un nom de table dynamique à l'aide de Dapper?

public GridData GetGridData(string schema, string table, TableDataParameters tableDataParameters) 
    { 
     using (var dbConnection = VarConnection) 
     { 
      dbConnection.Open(); 

      if (!this.TableExists(dbConnection, schema, table)) 
      { 
       throw new ItemNotFoundException($"Could not locate table {schema}.{table}."); 
      } 

      string orderyByClause = string.Join(",", tableDataParameters.SortModel.Select(s => $"[{s.ColId}] {(s.Sort.ToLower() == "asc" ? "asc" : "desc")}")); 

      var parameters = new DynamicParameters(); 

      string whereClause; 
      if (tableDataParameters.FilterModel == null || !tableDataParameters.FilterModel.Any()) 
      { 
       whereClause = "1=1"; 
      } 
      else 
      { 
       whereClause = string.Join(" AND ", tableDataParameters.FilterModel.Select((fm, i) => 
       { 
        string whereParam = $"whereParam{i}"; 
        parameters.Add(whereParam, fm.Filter); 

        if (fm.Operation == "startsWith") 
        { 
         return $"[{fm.Column}] LIKE @{whereParam} + '%'"; 
        } 
        throw new InvalidOperationException($"Unsupported filter operation '{fm.Operation}'"); 
       })); 
      } 

      var query = $"SELECT COUNT(1) [total] " + 
         $"FROM [{schema}].[{table}] " + 
         $"WHERE {whereClause} " + 
         $"SELECT * " + 
         $"FROM [{schema}].[{table}] " + 
         $"WHERE {whereClause} " + 
         $"ORDER BY {orderyByClause} " + 
         $"OFFSET {tableDataParameters.StartIndex.Value} ROWS " + 
         $"FETCH NEXT {tableDataParameters.StopIndex.Value - tableDataParameters.StartIndex.Value} ROWS ONLY"; 
      int total = 0; 
      using (var reader = dbConnection.ExecuteReader(query, parameters)) 
      { 
       // First batch, it's the count 
       if (reader.Read()) 
       { 
        total = reader.GetInt32(0); 
       } 

       var gridColumns = new List<GridColumn>(); 
       var gridRows = new List<string[]>(); 
       if (reader.NextResult() && reader.Read()) 
       { 
        for (int i = 0; i < reader.FieldCount; i++) 
        { 
         string key = reader.GetName(i); 
         gridColumns.Add(new GridColumn(key, key, null, "")); 
        } 

        var items = new object[reader.FieldCount]; 
        reader.GetValues(items); 
        gridRows.Add(items.Select(i => i.ToString()).ToArray()); 
       } 

       while (reader.Read()) 
       { 
        var items = new object[reader.FieldCount]; 
        reader.GetValues(items); 
        gridRows.Add(items.Select(i => i.ToString()).ToArray()); 
       } 

       return new GridData(tableDataParameters.StartIndex.Value, tableDataParameters.StopIndex.Value, total, gridRows.Count(), gridColumns.ToArray(), gridRows.ToArray()); 
      } 
     } 
    } 

Dois-je utiliser quelque chose comme DbCommandBuilder.QuoteIdentifier, https://msdn.microsoft.com/en-us/library/system.data.common.dbcommandbuilder.quoteidentifier(v=vs.110).aspx dans ce cas? Cela ne semble pas aider autant ici.

Merci!

+0

J'ai fini par utiliser une liste blanche. – TheTFo

Répondre

1

Les paramètres dynamiques sont un oxymore! Dapper facilite les paramètres, mais vous ne pouvez pas paramétrer les noms de tables et de colonnes. C'est une restriction de SQL, pas dapper. Si vous voulez vraiment faire cela, vous devez utiliser des méthodes dynamiques sql et string, et vous êtes seul en ce qui concerne l'injection SQL.

Vous serez plus heureux et vivrez plus longtemps si vous ne le faites pas. C'est juste une mauvaise route. Vous n'ajoutez pas beaucoup de valeur et vous risquez d'introduire une quantité de problèmes et de limitations.

Il semble que vous écrivez une application pour parcourir une base de données. De bons outils existent déjà pour cela!