【问题标题】:Left join with ServiceStack.OrmLite returns an empty object instead of null与 ServiceStack.OrmLite 的左连接返回一个空对象而不是 null
【发布时间】:2017-10-02 22:59:54
【问题描述】:

我创建了a repository with a complete example of what I'm trying to do。

我有以下架构:

class Order
{
    public int OrderId { get; set; }
}

class LineItem
{
    public int LineItemId { get; set; }
    public int OrderId { get; set; }
}

我正在使用 ServiceStack.OrmLite 左加入 Order 和 LineItem,使用以下代码:

var query = db.From<Order>()
              .LeftJoin<LineItem>()
              .Where(o => o.OrderId == 1);

var results = db.SelectMulti<Order, LineItem>(query);

SelectMulti() 返回一个List&lt;Tuple&lt;Order, LineItem&gt;&gt;。当订单没有订单项时,我会返回 new LineItem() 而不是 null。

我希望得到null 的回复,这样我就可以区分“此订单不存在订单项”和“此订单有一个具有默认值的订单项”。

我可以检查订单项的OrderId 是否等于订单的OrderId,但理论上我可以有OrderId 0 的订单,所以在这种情况下我不会'说不出来。

有没有更好的方法来使用 OrmLite 进行左连接?

【问题讨论】:

    标签: c# servicestack ormlite-servicestack


    【解决方案1】:

    我使用的快速而肮脏的解决方案是检查返回的相关对象是否为“空”。

    我用一个小的内联函数做到了,如下所示:

    bool IsEmptyObject<T>(T instance)
    {
        var empty = Activator.CreateInstance(instance.GetType());
        return empty.ToJson() == instance.ToJson();
    }
    

    【讨论】:

    • 这非常低效,Activator.CreateInstance() 在不缓存时很慢,并且每次都会分配一个新实例。 instance.GetType().GetDefaultValue().ToJson() == instance.ToJson() 效率更高,但如果您的 Type 是结构体或覆盖 Equals(),则使用 instance.GetType().GetDefaultValue().Equals(instance) 会更有效。
    【解决方案2】:

    我希望返回 null,以便区分“此订单不存在订单项”和“此订单有一个具有默认值的订单项”。

    LEFT JOIN 的问题是该行确实存在,但所有字段都返回为 null,OrmLite 映射到一个实例,其中没有初始化任何字段,这与不存在的行无法区分。

    我可以检查订单项的 OrderId 是否等于订单的 OrderId,但理论上我可以有一个 OrderId 为 0 的订单,所以在这种情况下我无法判断。

    这应该是不可能的,因为自动递增主键从 1(默认情况下)开始并向上递增。如果您有一个带有0 的int 主键,那么您应该将其视为无效状态(这可能表明它被错误地添加了),因此检查default(int) 就足够了。

    【讨论】:

    • 关于 PK,存在 PK 不自动递增的有效情况,或者 DBA 可能选择从 0 开始而不是 1。OrmLite 选择不支持这些是有效的情况,因为它们并不常见,但这种情况确实存在。
    • 如果模型具有不可为空的字段但数据库在该列中返回空值,特别是如果它是主键,则很好地表明连接右侧没有行.我意识到 OrmLite 不会询问数据库以确定该列是否可以为空,但不可为空的 .NET 属性可能是一个很好的启发式方法。 (此外,我查看了 OrmLite 的实现,我明白为什么如果不进行大量重构,这将难以实现。)
    • @StephenJennings 是的,如果所有字段都为空并且结果集包含 PrimaryKey,我们可以假设 null 而不是空对象。这在技术上是可行的,但我不认为订单拥有0 PK 是“有效”的。
    • 一个人为的例子:如果表是UnixUsers 而不是Orders,那么root 的PK 可能为0。
    • @StephenJennings UnixUsers 表没有自动递增 ID。
    猜你喜欢
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    相关资源
    最近更新 更多