在实体对象设计中处理 id
一段时间以来,我一直在思考如何处理由数据库分配标识符的对象。
表示表实体的典型对象可能如下所示:
public class Test
{
public int Id { get; private set; }
public string Something { get; set; }
}
假设我们想使用该对象在数据库中插入、检索和更新对象。至于检索和更新,我们没有问题,因为 Id 字段始终有一个值。
但是,如果我们想要将 Test 类型的新对象插入数据库,Id 字段仍然需要有一个值。我们可以只使用“0”,因为它不太可能用作数据库密钥,但实际上这不是一个好的设计。
同样,如果我们反转情况并使 Id 属性可为空,则可以对数据库尚未分配标识符的对象使用 null。但是,现在从数据库检索的对象可能没有标识符(类设计允许,但数据库设计不允许)
关于如何针对此问题进行良好设计有什么好的想法吗?
For a while I have been thinking about how to deal with objects which are assigned identifiers by the database.
A typical object representing a table entity may look like:
public class Test
{
public int Id { get; private set; }
public string Something { get; set; }
}
Suppose we would like to use this object for inserting, retrieving and updating objects in the database. As for retrieving and updating we have no problems, since the Id field always has a value.
However, if we want to insert a new object of type Test into the database, the Id field will still need to have a value. We could just use "0", as it is unlikely to be used as a database key, but really this is not a good design.
Likewise, if we invert the situation and make the Id property nullable, we could use null for objects which have not yet been assigned an identifier by the database. However, it is now possible for an object retrieved from the database to not have an identifier (as allowed by the class design, but not the database design)
Any good ideas on how to make a good design for this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
因此,您有一个包含数据库表的标识符作为字段的类,因此在检索/删除和更新的情况下,您的实体的标识符与数据库记录的标识符对齐。在插入的情况下,您可以检索刚刚插入的记录的标识值并使用该值更新您的实体。因此,您可以使用单独的存储过程来进行插入/更新/检索和删除。插入 SP 可以返回刚刚插入的记录的 ID 作为
输出参数
。希望我能回答你的问题。So, you have a class that contains database table's identifier as a field, so in case of retrieval/deletion and updation your entity's identifier is aligned with the database record's identifier. In case of insertion, you could retrieve the identify value of the record just inserted and update your entity with that value. So you could have separate store procedures for insertion/updation/retrieval and deletion. The insertion SP could return you the id of the record just inserted as a
out parameter
. Hope I answer your question.如果您将
id
视为在应用程序中识别/授予对象唯一性的一种方式,则这应该由数据库处理(除非当然,您有其他方法来分配标识符到对象)。如果不是(例如,它是由业务需求驱动的对象属性) -
0
是否有效/良好的设计价值纯粹取决于这些业务需求。从最终用户的角度来看,0
值是否有效?如果您觉得在应用程序中设置没有
ids
的对象是有问题的,您始终可以将对象属性包装到单独的类中。您将使用此类基本上仅用于携带尚未创建的对象的参数(创建过程通过数据库插入完成)。一旦插入对象、分配 ID 等 - 您就可以使用常规实体。一旦id = 0< 联系您的用户,他们会“哦,快点!那是什么?” 或“好吧..我知道该怎么做。” /代码>?
编辑
这个问题(或者更确切地说是我关于包装参数的回答)让我想起了一个曾经令我惊讶的事实。当孩子出生时,她并不存在于系统中,直到她的父母正式为她注册并分配给她个人身份号码。所以从技术上来说,如果没有 id,孩子就不存在(至少从系统的角度来看),即使每个人都知道她出生了之类的。数据库/您的应用程序也是如此 - 没有 id 的对象(数据库无法识别的对象)不存在 - 它只是一组参数。有点奇怪,但我希望我的观点很清楚:)
If you treat
id
as a way to identify/grant uniqueness to object within your application, this should be handled by database (unless of course, you have other ways to assign identifiers to objects).If it's not (as in, it's object's property driven by business needs) - whether
0
is valid/good design value or not depends on those business needs purely. Is0
valid value from say, end user point of view?You can always wrap your object properties into separate class, if you feel that having objects without
ids
set around in your application is problematic. You'll use such class essentially only for carrying parameters for not yet created object (creation process is finalized with database insert). Once the object gets inserted, id assigned and stuff - you can work with your regular entity. Will your user go "Oh, snap! What is that?" or "Ok.. I know what to do." once approached byid = 0
?Edit
This question (or rather my answer about wrapping parameters) reminded me of a fact that once surprised me. When a child is born, she doesn't exist in system until her parents officialy register her and she gets personal identification number assigned. So technically, without
id
- child doesn't exist (at least from system point of view), even tho everybody knows she was born and stuff. It's the same with database/your app - object withoutid
(one that database cannot identify) doesn't exist - it's just a set of parameters. Bit bizzare, but I hope my point is clear :)设计一个类,使 ID 为 0 表示该实体尚未被序列化,这并没有什么问题。我过去曾经构建过成功使用这种方法的系统。只需确保这些语义在您的 API 中得到了明确的定义,并且所有代码都遵循了这一含义。
需要注意的一个陷阱是使用 ID 定义相等关系(例如为字典生成哈希码)。只能对非零 ID 执行此操作。为了测试两个 ID 为零的相等性,可以使用引用相等性。
然而,由于未存储的实体的 ID 在将来的某个时刻可能会发生更改,因此此类对象永远不要存储在字典中,这一点非常重要。或者,至少,在保存之前必须从任何词典中删除此类项目,然后使用新 ID 进行恢复。
有了这一保留,这个设计应该可以正常工作。
There is nothing wrong with designing a class so that an ID of 0 indicates that the entity has not yet been serialized. I have built systems in the past that successfully used this approach. Just make sure that these semantics are well defined in your API, and that this meaning is respected in all of the code.
One trap to watch out for is using the ID to define an equality relationship (such as for generating hash codes for a dictionary). This must only be done for non-zero IDs. For testing equality with two IDs of zero, reference equality may be used.
However, since unstored entities may have their ID change at some point in the future, it is very important that such objects are never stored in a Dictionary. Or, at the very least, such items must be removed from any dictionaries before saving and then restored afterwards using the new ID.
With that one reservation, this design should work fine.