gpt4 book ai didi

c# - ServiceStack.OrmLite : using aliases in SqlExpression for anonymous types

转载 作者:行者123 更新时间:2023-11-30 17:25:14 27 4
gpt4 key购买 nike

我在这里发布这个问题,因为我仍在 ServiceStack 客户论坛上等待批准。这是一个相当具体的问题,所以我不希望很多人能提供帮助...... @mythz :)

我正在将 ServiceStack 从 v5.4 迁移到 v5.7,在 SqlExpression 中存在别名问题.

我编写了一个自定义的 sql concat 以在一列中获得“kind-of-csv-format”,以便在使用联合时将数据合并到一列中。从 SQL 方面来看,简化版本为:


SELECT CONCAT(Col1, ',', Col2) as Data FROM Table1
UNION ALL
SELECT CONCAT(Col3, ',', Col4, ',', Col5) as Data FROM Table2

在 C# 中,使用 OrmLite api,我这样做:

                var q1 = db.From<Table1>();
q1.Select(x => new
{
Data = Sql.Custom(q1.ConcatWithSeparator("@delimiter", y => new { y.Col1, y.Col2 }))
});

ConcatWithSeparator是我的自定义方法,调用底层 IOrmLiteDialectProvider.SqlConcat()在引擎盖下,在 @delimiter 之前插入匿名类型的成员之间。

这给了我: SELECT CONCAT("Table1"."Col1", @delimiter, "Table1"."Col2") AS DATA FROM "Table1"

这适用于 v5.4,但正如我注意到的,在 v5.7 中,方法 SqlExpression.SetAnonTypePropertyNamesForSelectExpression() 中引入了一个更改。( https://github.com/ServiceStack/ServiceStack.OrmLite/blob/v5.7/src/ServiceStack.OrmLite/Expressions/SqlExpression.cs )

            if (arg is ConditionalExpression ce ||                           // new { Alias = x.Value > 1 ? 1 : x.Value }
arg is BinaryExpression be || // new { Alias = x.First + " " + x.Last }
arg is MemberExpression me || // new { Alias = DateTime.UtcNow }
arg is ConstantExpression ct) // new { Alias = 1 }
{
IOrmLiteConverter converter;
var strExpr = !(expr is PartialSqlString) && (converter = DialectProvider.GetConverterBestMatch(expr.GetType())) != null
? converter.ToQuotedString(expr.GetType(), expr)
: expr.ToString();

return new PartialSqlString(strExpr + " AS " + member.Name);
}

特别是关于这张支票:

            if (
...
arg is MemberExpression me || // new { Alias = DateTime.UtcNow }
...
)

new { x.Col1 } 的计算结果也为真,因为它是 new { Col1 = x.Col1 } 的缩写这进一步使sql语法Col1 as Col1

在我的 concat 中,它导致错误的 SQL SELECT CONCAT("Table1"."Col1" AS Col1, @delimiter, "Table1"."Col2" AS Col2) AS DATA FROM "Table1"

所以真正的问题是,是否应该进行额外检查,如果它是 MemberExpression me , 还有 me.Member.Name != member.Name ?或者可能有一些额外的配置选项来绕过别名生成?

或者...有没有其他更容易实现的方法,我想做什么? (我必须支持 MySQL、MSSQL、Sqlite 和 PostgreSQL)。

更新,关于下面的@mythz 回答

不幸的是,它仍然没有按预期工作。但我认为,我们越来越近了。此处的转换器:

IOrmLiteConverter converter;
var strExpr = !(expr is PartialSqlString) && (converter = DialectProvider.GetConverterBestMatch(expr.GetType())) != null
? converter.ToQuotedString(expr.GetType(), expr)
: expr.ToString();

return new PartialSqlString(strExpr != member.Name
? strExpr + " AS " + member.Name
: strExpr);

将表达式计算为带引号的字符串,所以最后有一个检查 "\"Col1\"" != "Col1" .

另外,我还写了一个版本ConcatWithSeparator<Table1, Table2>可以将 lambda 作为 (t1, t2) => new { t1.Col1, t2.Col1 } .在这种情况下,它会将成员表达式计算为类似于 "Table1"."Col1" 的内容。 (取决于 DBMS)- 我希望,多表版本不是一蹴而就的,它仍然可以在没有原始 sql 的情况下实现...

最佳答案

我已将其更改为当别名与 this commit 中的名称相同时不使用别名.

此更改适用于现在的最新 v5.7.1 available on MyGet .

关于c# - ServiceStack.OrmLite : using aliases in SqlExpression for anonymous types,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58974112/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com