gpt4 book ai didi

c# - object == object 而不是 object.id == object.id 潜在问题

转载 作者:行者123 更新时间:2023-11-30 16:59:13 27 4
gpt4 key购买 nike

我继承了一个非常草率的项目,我的任务是解释为什么它不好。我注意到他们在整个代码中都进行了这样的比较

(IQueryable).FirstOrDefault(x => x.Facility == facility && x.Carrier == shipCode.Carrier

在上面的示例中,x.Facility 来自数据库,而 facility 来自 shipment.facility,它在 nhibernate 中被映射为一个复杂对象。

我希望看到 .FirstOrDefault(x => x.Facility.ID == facility.ID

起初我认为比较整个对象可能会导致问题,如果数据库中的设施记录发生更改,那么存储在 shipment 中的设施显然会有所不同。

经过更多考虑后,我意识到 shipment.facility 是从 id 填充的,因此即使该设施记录发生变化,它也应该匹配。

我仍然感觉不对,我看到这有很多错误并且很难追踪?将整个对象与一个 ID 进行比较是否有什么特别错误的地方。

最佳答案

将我之前的评论扩展为答案:

我认为当 ORM 允许时,这实际上是好的做法。我没有使用 NHibernate 的经验,所以对于其余的答案,我将假设它实际上确实以一种明智的方式实现了平等(例如比较主键)。您应该确保是这种情况,否则代码不仅糟糕而且可能存在错误。

打个比方,暂时忘掉 SQL,假设您正在处理一个不属于任何 ORM 的 POCO。您想要在以下选项之间进行选择:

方法一:IEquatable

public class Facility : IEquatable<Facility>
{
public int Id {get; private set;}
//The rest of the properties

public bool Equals(Facility other)
{
return other.Id == Id;
}
}

(您还想覆盖 Object.Equals,但为了简洁起见,我将排除它)

方法二:IEqualityComparer

public class Facility
{
public int Id {get; private set;}
//The rest of the properties
}

public class FacilityIdsMatchEqualityComparer : IEqualityComparer<Facility>
{
public bool Equals(Facility x, Facility y)
{
return x.Id == y.Id;
}
}

(为简洁起见,也排除了GetHashCode)。

这两种方法哪种更好?好吧,我会说它是方法 1 的明显优势。它遵循方法 2 不遵循的两个重要原则:

  • 不要重复自己。在第二种方法中,任何试图比较设施的代码都必须使用 FacilityIdsMatchEqualityComparer。这个事实,即需要使用特定的相等比较逻辑,会在整个解决方案中喷洒,每次你想比较它们时都会重复。

  • 单一职责原则。不仅每个进行比较的类都需要重复代码,而且该代码承担了不属于该类的责任。应该由Facility来表达相等性的实现,而不是每个想用它的类都说是通过比较Id来完成的。 (是的,我知道你可以做到,比如说,FacilityEqualityComparer,这样调用类就不知道相等比较是如何完成的,但这样做的目的是类比OP,其中确切的比较逻辑被硬编码到每个比较中)

因此,回到实际问题上来,这个类比非常接近地反射(reflect)了您在这里遇到的情况。它不像实现 IEquatableFacility 那样简单,但原理是完全一样的:ORM 自己负责如何实现相等性检查,而不是推送使用它编写代码的责任。

这意味着如果我正在编写代码,比如说在数据访问层之外,我可以说“我想检查这两个对象是否相等,所以我会写 object1 == object2”,而不是“我想检查这两个对象是否相等,这两个对象是实体,由于我们实现持久性的方式,这意味着当我检查是否相等时将转换为 SQL 查询,所以我需要像编写 SQL 一样编写此检查,这意味着我需要比较它们的主键,这要么通过检查属性,要么通过我对数据访问层约定的了解,我知道这意味着比较它们的 Id 属性。所以我将编写 object1.Id == object2.Id”。

ORM 并不完美,您不能总是完全抽象出底层 SQL 数据库,但如果可以,您应该这样做!

关于c# - object == object 而不是 object.id == object.id 潜在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23998126/

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