有一段时间我一直在考虑如何处理由数据库分配标识符的对象。
表示表实体的典型对象可能如下所示:
public class Test
{
public int Id { get; private set; }
public string Something { get; set; }
}
假设我们希望使用此对象来插入,检索和更新数据库中的对象。至于检索和更新,我们没有问题,因为Id字段总是有一个值。
但是,如果我们要将Test类型的新对象插入数据库,则Id字段仍需要具有值。我们可以使用“0”,因为它不太可能被用作数据库密钥,但实际上这不是一个好的设计。
同样,如果我们反转情况并使Id属性可以为空,我们可以对数据库尚未分配标识符的对象使用null。但是,现在可以从数据库中检索的对象没有标识符(如类设计所允许,但不是数据库设计)
关于如何为这个问题做好设计的任何好主意?
答案 0 :(得分:3)
如果您将id
视为在应用程序中识别/授予对象唯一性的方法,则应由数据库处理(除非当然,您还有其他方式来分配标识符对象)。
如果不是(因为它的对象的属性由业务需求驱动) - 0
是否有效/良好的设计价值取决于纯粹的业务需求。从最终用户的角度来看,0
是否有效值?
如果您认为在应用程序中设置了没有ids
的对象是有问题的,您始终可以将对象属性包装到单独的类中。您将使用此类主要仅用于携带尚未创建的对象的参数(创建过程使用数据库插入完成)。一旦插入对象,id分配和填充 - 您可以使用常规实体。您的用户是否会“哦,快攻!这是什么?”或“好的......我知道该怎么做。”一旦被id = 0
接近?< / p>
修改强>
这个问题(或者说我关于包装参数的答案)让我想起曾经让我感到惊讶的事实。当孩子出生时,在她的父母正式注册她并且她获得个人识别号码之前,她不存在于系统中。所以在技术上,没有id
- 孩子不存在(至少从系统的角度来看),即使是每个人都知道她出生了。与数据库/您的应用程序相同 - 没有id
的对象(数据库无法识别的对象)不存在 - 它只是一组参数。有点古怪,但我希望我的观点很清楚:)
答案 1 :(得分:3)
设计类没有任何问题,因此ID为0表示实体尚未序列化。我过去已经建立了成功使用这种方法的系统。只需确保在API中明确定义了这些语义,并且在所有代码中都遵循这一含义。
需要注意的一个陷阱是使用ID来定义相等关系(例如为字典生成哈希码)。这只能用于非零ID。为了测试两个ID为零的相等性,可以使用引用相等性。
但是,由于未存储的实体在将来的某个时刻可能会更改其ID,因此这些对象永远不会存储在字典中非常重要。或者,至少在保存之前必须从任何词典中删除这些项目,然后使用新ID恢复。
通过这一项保留,此设计应该可以正常工作。
public class Test : IEquatable<Test>
{
/// <summary>
/// The unique identifier for this Test entity, or zero if this
/// Test entity has not yet been serialized to the database.
/// </summary>
public int Id { get; private set; }
public string Something { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as Test);
}
public bool Equals(Test other)
{
if (other == null)
return false;
// Distinct entities may exist with the Id value of zero.
if (Id == 0)
return object.ReferenceEquals(this, other);
return Id == other.Id;
}
/// <summary>
/// Gets a hash code for this Test entity. Warning: an instance with
/// an Id of zero will change its identity when saved to the DB. Use with care.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
return Id;
}
}
答案 2 :(得分:1)
因此,您有一个包含数据库表标识符的类作为字段,因此在检索/删除和更新的情况下,您的实体的标识符与数据库记录的标识符对齐。如果插入,您可以检索刚刚插入的记录的标识值,并使用该值更新您的实体。因此,您可以使用单独的存储过程来插入/更新/检索和删除。插入SP可以返回刚插入out parameter
的记录的ID。希望我回答你的问题。