4

我想创建一个可以采用表达式并使用 Linq-To-Sql 生成所需 SQL 语句的存储库模型。

例如,我有一个这样的功能:

// Possible criteria
Expression<Func<Purchase,bool>> criteria1 = p => p.Price > 1000;

// Function that should take that criteria and convert to SQL statement
static IEnumerable<Customer> GetCustomers (Expression<Func<Purchase,bool>> criteria)
{
   // ...
}

在函数内部,我想使用 Linq-To-Sql 将条件转换为 SQL 语句。

我知道您可以使用它DataContext.Log来查看执行的查询并在执行DataContext.GetCommand(query).CommandText之前查看完整的查询。但是,我只想生成整个表达式的一部分。

我希望完成的是让我的存储库抽象底层技术(Linq-to-Sql、Dapper 等)。这样我就可以将表达式传递到存储库,让它生成正确的语句并使用正确的技术来执行它。

4

2 回答 2

2

你可以这样做:

string sql = DataContext.GetTable<Customer>().Where(criteria).ToString();

ToString() 为您提供 SQL 表达式。然后,您可以使用正则表达式提取 WHERE 子句。

于 2011-11-23T12:09:35.950 回答
1

这是我用来构建自己的谓词以在 Where 函数中使用的代码摘录。编译器无法处理复杂对象的可枚举,所以你必须自己做。

本质上,代码被传递了一个可枚举的(字符串代码,字符串交换)元组,然后构建一个表达式来检索所有具有 Security.Code == tuple.Code AND (Security.MasterExchangeForStocksId == tuple.exchange OR SecurityExchangeId == tuple.exchange)。

CreateTrEntitiesAsync() 仅返回具有 DbSet 安全属性的实体框架上下文。

public async Task<Security[]> GetSecurities(IEnumerable<(string code, string exchange)> tickers)
{
    using (var ctx = await CreateTrEntitiesAsync())
    {
        var securityExpr = Expression.Parameter(typeof(Security), "security");
        Expression expr = null;
        Expression exprToadd;

        foreach (var item in tickers)
        {
            exprToadd = Expression.And(
                Expression.Equal(Expression.Property(securityExpr, nameof(Security.Code)), Expression.Constant(item.code)),
                Expression.Or(
                    Expression.Equal(Expression.Property(Expression.Property(securityExpr, nameof(Security.Exchange)), nameof(Exchange.MasterExchangeForStocksId)), Expression.Constant(item.exchange)),
                    Expression.Equal(Expression.Property(securityExpr, nameof(Security.ExchangeId)), Expression.Constant(item.exchange))
                )
            );

            if (expr == null)
                expr = exprToadd;
            else
                expr = Expression.Or(expr, exprToadd);
        }

        var criteria = Expression.Lambda<Func<Security, bool>>(expr, new ParameterExpression[] { securityExpr });
        var items = ctx.Securities.Where(criteria);
        return await items.ToArrayAsync();
    }
}
于 2019-07-16T09:30:02.707 回答