我的示例将涉及用于讨论目的的伪C#代码,但这并非特定于任何单一语言或数据库工具。
采用简单的模型
Customer { string Id }
当我存储new Customer()
时使用RavenDB,它会在执行时为我生成一个id,假设为“Customers / 234”。在这种情况下,我很好地接受id是RavenDB的一个方面。从根本上说,这与Guid.NewGuid().ToString()
完全没有区别,因为它创建了一个没有人类可理解含义的标识符,只是实现了全局唯一性的目标(对于这个数据库)。这可以说是一个更好的guid版本,并且可以创建更好的URL并允许人们传达他们的id,如果它比16个随机十六进制字符串更容易。
在另一种情况下:
User { string UserName, string Id }
在这种情况下,我想将真正的语义含义放入我的Id,而不是仅仅是一个唯一的数字。
使用RavenDB可以实现类似于:
store.Conventions.DocumentKeyGenerator = (entity) =>
{
User user = entity as User;
if(user == null)
return defaultKeyGeneration (entity);
return "Users/" + user.UserName;
}
然后在此商店运营期间,您最终会得到“Users / dotnetchris”
我也可以通过让用户拥有Id的简单属性,而不是使用只读属性来解决这个问题:
User {
string Id { get { return "Users/" + UserName }
我很难决定哪一个是这个结构的适当位置。
我倾向于它应该直接包含在类中,因为这为您提供了一些信息,即通过用户输入的id加载此对象很容易,而不需要查询到数据库来查找{{1} }
答案 0 :(得分:1)
它似乎高度依赖于数据如何在数据库中引用或不引用。如果数据库设计中某种约束需要“完整”ID(即Users/name
),那么将其保持在数据库附近将是更好的选择,但如果不是这样,那么您将受益更多保持它作为域模型的一部分,以允许代码的灵活性(根据您的最终代码示例)。
答案 1 :(得分:0)
作为一项规则,我努力让每个标识符都由应用程序拥有,而不是数据库。我将通过模型身份所有权的唯一原因是性能原因,例如:一个需要复制并且有5亿行的SQL表。