由于您以 Azure CosmosDB 为目标,因此无需编写自己的查询生成器,CosmosDB 客户端库 ( Microsoft.Azure.Cosmos
) 有一个内置的.
在您的情况下,使用QueryDefinition
andWithParameter
来构建强类型查询。该WithParameter
方法接受值 asobject
并为您处理特定于类型的逻辑。
当您使用动态查询时,下面的代码显示了如何使用命名参数从字典中安全地构建查询子句。WHERE
永远不要将查询参数值直接嵌入查询 SQL 本身,因为这样做会导致 SQL 注入,这是一件非常糟糕的事情。
更新enum
:
我承认我不熟悉 Azure CosmosDB 客户端库,尽管我确实快速查看了文档并在 ILSpy 中浏览了该库。
至于处理enum
值:该QueryDefinition.WithParameter
方法应该enum
正确处理值,因为它在其.Value
属性中保留了装箱的枚举值。
如果不是,则可以像这样将 any 转换enum
为 an - 尽管使用装箱(虽然可以将任何枚举强制转换为不需要运行时 IL 发射的强制转换,这超出了此答案的范围,但我有一个如果您有兴趣,请在我的 GitHub Gists 中实现):Int32
Int64
我已经更新了下面的代码以使用这个foreach
循环来检查Enum
(它匹配任何和所有 enum
类型,不管它们的底层类型如何,尽管如果你有任何enum : Int64
值超出Int32
's 范围的枚举,这个例子将会失败——但这对修复,所以留给读者练习)。
foreach( var kvp in parameters )
{
if( kvp.Value is Enum e )
{
Int32 enumAsInt32 = (Int32)Convert.ChangeType( e, TypeCode.Int32 );
query = query.WithParameter( kvp.Key, enumAsInt32 );
}
else
{
query = query.WithParameter( kvp.Key, kvp.Value );
}
}
我原来的答案的其余部分:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
//
public static QueryDefinition BuildCosmosQuery( Dictionary<String,Object> parameters )
{
String sqlText = "SELECT * FROM foobar AS f WHERE " + GetWhereClauses( "f", parameters.Keys );
QueryDefinition query = new QueryDefinition( sqlText );
foreach( var kvp in parameters )
{
if( kvp.Value is Enum e )
{
Int32 enumAsInt32 = (Int32)Convert.ChangeType( e, TypeCode.Int32 );
query = query.WithParameter( kvp.Key, enumAsInt32 );
}
else
{
query = query.WithParameter( kvp.Key, kvp.Value );
}
}
return query;
}
private static String GetWhereClauses( String tableAlias, IEnumerable<String> parameterNames )
{
return parameterNames
.Select( pn => "{0}.{1} = @{1}".FmtInv( tableAlias, pn ) )
.StringJoin( separator: " AND " );
}
//
public static class Extensions
{
public static String StringJoin( this IEnumerable<String> source, String separator )
{
return String.Join( values: source, separator: separator );
}
public static String FmtInv( this String format, params Object[] args )
{
return String.Format( CultureInfo.InvariantCulture, format, args: args );
}
}
请参阅QueryWithSqlParameters
此代码示例中的方法以了解如何使用QueryDefinition
.