Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 数据模型驱动的资源Id是资源还是数据库的一个方面?_Database_Model_Uniqueidentifier_Ownership - Fatal编程技术网

Database 数据模型驱动的资源Id是资源还是数据库的一个方面?

Database 数据模型驱动的资源Id是资源还是数据库的一个方面?,database,model,uniqueidentifier,ownership,Database,Model,Uniqueidentifier,Ownership,为了便于讨论,我的示例将涉及伪C#代码,但这并不特定于任何单一语言或数据库工具 以一个简单的模型为例 Customer{string Id} 在我存储newcustomer()时使用RavenDB它将在执行时为我生成一个id,假设为“Customers/234”。在这个场景中,我可以接受id是RavenDB的一个方面。从根本上讲,这与Guid.NewGuid().ToString()完全没有区别,因为它创建的标识符没有人类可以理解的含义,只是实现了全局唯一性的目标(对于此数据库)。这可以说是一个

为了便于讨论,我的示例将涉及伪C#代码,但这并不特定于任何单一语言或数据库工具

以一个简单的模型为例

Customer{string Id}

在我存储
newcustomer()时使用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;
}
在这个商店运营过程中,你会得到“用户/dotnetchris”

我也可以通过使用只读属性,而不是让用户拥有一个简单的Id属性:

User {
    string Id { get { return "Users/" + UserName }
我很难决定哪一个地方适合这个建筑


我倾向于将其直接包含在类中,因为这提供了一个信息,即可以轻松地从用户输入中按id加载此对象,而无需实际查询数据库以查找
用户。其中(user.UserName==“dotnetchris”)

它似乎高度依赖于数据在数据库中的引用方式。如果数据库设计中的某种约束需要“完整”ID(即
Users/name
),那么将其保留在数据库附近将是一个更好的选择,但如果不是这样,则将其保留为域模型的一部分以允许代码的灵活性(根据最终的代码示例)将使您受益更多.

作为一项规则,我努力使每个标识符都归应用程序所有,而不是数据库所有。我将传递模型标识的所有权的唯一原因是性能原因,例如需要复制且有5亿行的SQL表。

Users/name保证全局唯一性,任何其他文档都不可能具有该id(有效)。如果没有用户/Name的值在其他类型中使用,则无法再保证其唯一性。虽然这是从标准的RavenDB约定派生出来的,但我同意使用类型名作为分隔符的基本前提。因此,虽然RavenDB可能也要求ID是唯一的(因为没有真正的表),但能够唯一地提供信息也是一项业务要求,我承认,这种约定与任何约定一样好,即使不是最好的时期。如果唯一性是必要的,那么我认为让它更接近数据库是最好的。这样做时,唯一标识符在数据库和域模型中都是唯一的。如果
用户名
部分本身就需要(在不需要唯一性的情况下,等等),那么就可以很容易地去掉该部分。顺便说一句,我在数据范围内引用的任何全局点,不一定像guid那样在全球范围内是独一无二的。实际上我正在尝试实现其中一种解决方案。我喜欢DocumentKeyGenerator中的生成,因为它将密钥生成代码隔离到单个位置。但是,RavenDb提供了一种加载方式,允许按Id加载实体,如果您还没有应用正确前缀的Id,则需要一种在密钥生成系统之外应用前缀的方法。@ShaneH我同意您的说法,它将前缀隔离到1位置,然而,我不确定这是不是一件好事,因为你所有的物体都失去了理解力,这就是为什么我提出这个问题的原因。如果我需要从它们的关键部分构造这些Id来满足负载,我可能会创建一个类似于
Id.For(this.RouteData)
的类,在这个类中有一个泛型类型的开关,我将
返回“users/{userName}”。HenriFormat(RouteData)