Closed ddabb closed 11 months ago
可能当时比较忙没看到这个 issues
像这种复杂的问题,请提供一个能重现的 console app,我拿到后可以直接重现 debug
您有空提供一下 demo,先关闭 issues
@2881099 我也遇到了这个bug,希望重新打开该issue。
我可以给出一个相对小的复现代码,假设有一张UserInfo表:
public class UserInfo
{
[Column(IsIdentity = true, IsPrimary = true)]
public int Id { get; set; }
public int Role { get; set; }
public int Points { get; set; }
}
复现代码如下:
// int[] ids1 = [1, 3, 5], ids2 = [2, 4, 6];
int id1 = 1, id2 = 2;
var query1 = freeSql.Select<UserInfo>()
//.Where(u => ids1.Contains(u.Id))
.Where(u => u.Id == id1)
.WithTempQuery(u => new
{
GroupNo = 6,
Points = (int)SqlExt.Sum(u.Points).ToValue()
});
var query2 = freeSql.Select<UserInfo>()
// .Where(u => ids2.Contains(u.Id))
.Where(u => u.Id == id2)
.WithTempQuery(u => new
{
GroupNo = 6,
Points = (int)SqlExt.Sum(u.Points).ToValue()
});
var sql = freeSql.Select<UserInfo>()
.Where(u => u.Role == 1)
.WithTempQuery(u => new
{
GroupNo = 6,
Count = (int)SqlExt.Count(u.Id).ToValue()
})
.FromQuery(query1, query2) // 这里query1、query2的结构相同
.LeftJoin(p => p.t1.GroupNo == p.t2.GroupNo)
.LeftJoin(p => p.t1.GroupNo == p.t3.GroupNo)
.ToSql(p => new
{
p.t1.Count,
Points1 = p.t2.Points,
Points2 = p.t3.Points
});
打印出的SQL如下:
SELECT a.[Count] as1, htb.[Points] as2, htc.[Points] as3
FROM (
SELECT 6 [GroupNo], count(a.[Id]) [Count]
FROM [UserInfo] a
WHERE (a.[Role] = 1) ) a
LEFT JOIN (
SELECT 6 [GroupNo], sum(a.[Points]) [Points]
FROM [UserInfo] a
WHERE (a.[Id] = 1) ) htb ON a.[GroupNo] = htb.[GroupNo]
LEFT JOIN (
SELECT 6 [GroupNo], sum(a.[Points]) [Points]
FROM [UserInfo] a
WHERE (a.[Id] = 1) ) htc ON a.[GroupNo] = htc.[GroupNo]
将代码中过滤条件换成id数组后,SQL如下:
SELECT a.[Count] as1, htb.[Points] as2, htc.[Points] as3
FROM (
SELECT 6 [GroupNo], count(a.[Id]) [Count]
FROM [UserInfo] a
WHERE (a.[Role] = 1) ) a
LEFT JOIN (
SELECT 6 [GroupNo], sum(a.[Points]) [Points]
FROM [UserInfo] a
WHERE (((a.[Id]) in (1,3,5))) ) htb ON a.[GroupNo] = htb.[GroupNo]
LEFT JOIN (
SELECT 6 [GroupNo], sum(a.[Points]) [Points]
FROM [UserInfo] a
WHERE (((a.[Id]) in (1,3,5))) ) htc ON a.[GroupNo] = htc.[GroupNo]
可以看到FromQuery的T1和T2结构相同时,后者where条件被前者覆盖了,导致SQL查询错误。
区分一下每个 WithTempQuery 的类型,避免使用相同的匿名类型,随便加个属性区分就可以了
不修复吗?那文档里在FromQuery的用法上,可能要申明一下了。
调用链太长,暂时不好解决,使用时区分一下解决吧
var query1 = freeSql.Select<UserInfo>()
//.Where(u => ids1.Contains(u.Id))
.Where(u => u.Id == id1)
.WithTempQuery(u => new
{
GroupNo = 6,
Points = (int)SqlExt.Sum(u.Points).ToValue(),
Flag1 = 1
});
var query2 = freeSql.Select<UserInfo>()
// .Where(u => ids2.Contains(u.Id))
.Where(u => u.Id == id2)
.WithTempQuery(u => new
{
GroupNo = 6,
Points = (int)SqlExt.Sum(u.Points).ToValue(),
Flag2 =1 //与上面的匿名类型区分
});
workaround的确比较简单,也可以将Points分别命名成Points1和Point2,不需要额外的字段。
主要是这个问题会发生在运行时,编译期不太容易察觉。
如果从源代码层面不太好处理的话,我在想能否通过编写一个分析器,在编译期检测出这种情况然后直接报错或者提示警告。
数据库版本
sqlserver 2019
安装的Nuget包
package id="FreeSql" version="3.2.690" targetFramework="net4"
.net framework 已经在Freesql 的微信群里面反馈,仅做登记,跟进进展。