Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

发布于 2024-09-04 21:00:23 字数 1557 浏览 3 评论 0原文

我有以下 Subsonic 3.0 查询,其中包含嵌套的 NotIn 查询:

public List<Order> GetRandomOrdersForNoReason(int shopId, int typeId)
{
    // build query    
    var q = new SubSonic.Query.Select().Top("1")
        .From("Order")
        .Where("ShopId")
        .IsEqualTo(shopId)
        .And(OrderTable.CustomerId).NotIn(
            new Subsonic.Query.Select("CustomerId")
                .From("Customer")
                .Where("TypeId")
                .IsNotEqualTo(typeId))
            .OrderDesc("NewId()");

    // Output query
    Debug.WriteLine(q.ToString());   

    // returned typed list
    return q.ExecuteTypedList<Order>();
}

内部查询似乎不正确:

SELECT TOP 1 *
 FROM [Order]
 WHERE ShopId = @0 AND CustomerId NOT IN (SELECT CustomerId
 FROM [Customer]
 WHERE TypeId = @0)
 ORDER BY NewId() ASC

您会注意到两个参数都是 @0。我假设对于每个“新”选择查询都枚举了参数(从零开始)。但是,在嵌套两个 Select 查询的情况下,我希望输出有两个名为 @0@1 的参数。

我的查询基于 Rob Conery 在他的博客上提供的一个,作为“Pakala”查询工具的预览,该工具后来成为 Subsonic 3。他的例子是:

int records = new Select(Northwind.Product.Schema)
    .Where("productid")
    .In(
        new Select("productid").From(Northwind.Product.Schema)
        .Where("categoryid").IsEqualTo(5)
        )
    .GetRecordCount();

还有其他人看到过这种行为吗?这是一个错误,还是一个错误或我的部分?由于我是 Subsonic 的新手,我猜测这可能是我的程序员错误,但如果可能的话我想确认。

I have the following Subsonic 3.0 query, which contains a nested NotIn query:

public List<Order> GetRandomOrdersForNoReason(int shopId, int typeId)
{
    // build query    
    var q = new SubSonic.Query.Select().Top("1")
        .From("Order")
        .Where("ShopId")
        .IsEqualTo(shopId)
        .And(OrderTable.CustomerId).NotIn(
            new Subsonic.Query.Select("CustomerId")
                .From("Customer")
                .Where("TypeId")
                .IsNotEqualTo(typeId))
            .OrderDesc("NewId()");

    // Output query
    Debug.WriteLine(q.ToString());   

    // returned typed list
    return q.ExecuteTypedList<Order>();
}

The internal query appears to be incorrect:

SELECT TOP 1 *
 FROM [Order]
 WHERE ShopId = @0 AND CustomerId NOT IN (SELECT CustomerId
 FROM [Customer]
 WHERE TypeId = @0)
 ORDER BY NewId() ASC

You'll notice that both parameters are @0. I'm assuming that the parameters are enumerated (starting at zero), for each "new" Select query. However, in this case where the two Select queries are nested, I would have expected the output to have two parameters named @0 and @1.

My query is based on one that Rob Conery gave on his blog as a preview of the "Pakala" query tool that became Subsonic 3. His example was:

int records = new Select(Northwind.Product.Schema)
    .Where("productid")
    .In(
        new Select("productid").From(Northwind.Product.Schema)
        .Where("categoryid").IsEqualTo(5)
        )
    .GetRecordCount();

Has anyone else seen this behavior? Is it a bug, or is this an error or my part? Since I'm new to Subsonic I'm guessing that this probably programmer error on my part but I'd like confirmation if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萤火眠眠 2024-09-11 21:00:24

刚刚在最新版本中遇到了完全相同的问题,因此显然尚未修复。我尝试切换条件的顺序(首先放置 NotIn 条件),结果成功了。新代码如下所示,它生成参数@0和@1而不是@0和@0:

var q = new SubSonic.Query.Select().Top("1")
    .From("Order")
    .Where(OrderTable.CustomerId).NotIn(
        new Subsonic.Query.Select("CustomerId")
            .From("Customer")
            .Where("TypeId")
            .IsNotEqualTo(typeId)
    )
    .And("ShopId")
    .IsEqualTo(shopId)
    .OrderDesc("NewId()");

Just came across this exact same issue in the latest release, so apparently it hasn't been fixed yet. I tried switching the order of the conditions (putting the NotIn condition first) and that did the trick. Here's what the new code looks like, which produced parameters @0 and @1 instead of @0 and @0:

var q = new SubSonic.Query.Select().Top("1")
    .From("Order")
    .Where(OrderTable.CustomerId).NotIn(
        new Subsonic.Query.Select("CustomerId")
            .From("Customer")
            .Where("TypeId")
            .IsNotEqualTo(typeId)
    )
    .And("ShopId")
    .IsEqualTo(shopId)
    .OrderDesc("NewId()");
极致的悲 2024-09-11 21:00:24

我不确定 SubSonic 3,但在 SubSonic 2 中,如果您运行此代码,将首先执行内部查询,第二个查询会将 CategoryIds 全部定义为查询中的参数。
也许这是一个错误,您应该将其发布到 github 上。

不管怎样,你可以让你的查询暂时工作,并且表现得像 SubSonic 2 子查询一样,只需做一点小小的改变:

var q = new SubSonic.Query.Select().Top("1")
    .From("Order")
    .Where("ShopId")
    .IsEqualTo(shopId)
    .And(OrderTable.CustomerId).NotIn(
        new Subsonic.Query.Select("CustomerId")
            .From("Customer")
            .Where("TypeId")
            .IsNotEqualTo(typeId)
            .ExecuteTypedList<int>()
    )
    .OrderDesc("NewId()");

NotIn 应该采用 IEnumerable 作为参数,但 q 在执行外部部分之前将包含整个 CustomerId 列表作为参数。

这不是一个真正的解决方案,但目前是一个快速修复(如果它不会对性能产生太大影响)。

I'm not sure about SubSonic 3 but in SubSonic 2 if you would run this code the inner query would be executed first and the second query would have the CategoryIds allready defined as a parameter in the query.
Maybe this is a bug and you should post it on github.

Anyway you could make your query work for the moment and behave like a SubSonic 2 Subquery with this little change:

var q = new SubSonic.Query.Select().Top("1")
    .From("Order")
    .Where("ShopId")
    .IsEqualTo(shopId)
    .And(OrderTable.CustomerId).NotIn(
        new Subsonic.Query.Select("CustomerId")
            .From("Customer")
            .Where("TypeId")
            .IsNotEqualTo(typeId)
            .ExecuteTypedList<int>()
    )
    .OrderDesc("NewId()");

NotIn should take a IEnumerable as a parameter but q will contain the whole list of CustomerIds as a parameter before the outer part is executed.

Not a real solution but a quick fix for the moment (if it doesn't affect performance to much).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文