Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FromQuery T1,T2,T3 返回相同结构时,表关联异常的问题的问题 #1620

Closed
ddabb opened this issue Sep 18, 2023 · 9 comments
Closed

Comments

@ddabb
Copy link

ddabb commented Sep 18, 2023

数据库版本

sqlserver 2019

安装的Nuget包

package id="FreeSql" version="3.2.690" targetFramework="net4"

.net framework
FromQuery T1,T2,T3识别的问题
已经在Freesql 的微信群里面反馈,仅做登记,跟进进展。

@2881099
Copy link
Collaborator

2881099 commented Dec 8, 2023

可能当时比较忙没看到这个 issues

像这种复杂的问题,请提供一个能重现的 console app,我拿到后可以直接重现 debug

@2881099
Copy link
Collaborator

2881099 commented Dec 8, 2023

您有空提供一下 demo,先关闭 issues

@2881099 2881099 closed this as completed Dec 8, 2023
@LeaFrock
Copy link

@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]

@LeaFrock
Copy link

可以看到FromQuery的T1和T2结构相同时,后者where条件被前者覆盖了,导致SQL查询错误。

@2881099
Copy link
Collaborator

2881099 commented Jun 26, 2024

区分一下每个 WithTempQuery 的类型,避免使用相同的匿名类型,随便加个属性区分就可以了

@LeaFrock
Copy link

不修复吗?那文档里在FromQuery的用法上,可能要申明一下了。

@2881099
Copy link
Collaborator

2881099 commented Jun 26, 2024

调用链太长,暂时不好解决,使用时区分一下解决吧

@2881099
Copy link
Collaborator

2881099 commented Jun 26, 2024

        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 //与上面的匿名类型区分
            });

@LeaFrock
Copy link

workaround的确比较简单,也可以将Points分别命名成Points1和Point2,不需要额外的字段。

主要是这个问题会发生在运行时,编译期不太容易察觉。

如果从源代码层面不太好处理的话,我在想能否通过编写一个分析器,在编译期检测出这种情况然后直接报错或者提示警告。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants