nhibernate是否可以在不作为主键的情况下检查唯一约束

nhibernate是否可以在不作为主键的情况下检查唯一约束,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我有一个简单的类,它有一个名称成员,用于唯一标识实例。该类在多个映射中引用,该映射将使用名称(因为它是主键)创建映射表。所涉及的字符串类型使其速度非常慢(长度>128个字符,通常只在最后几个字符中有所不同)。为了加快速度,我想为连接创建一个auto_increment列(我使用的是MySQL),同时仍然能够让nhibernate使用Name-列来排序我的对象的唯一性 下面是一个它看起来像什么的例子。实际上,这些物体要大得多 class MyObject{ public String Name

我有一个简单的类,它有一个
名称
成员,用于唯一标识实例。该类在多个映射中引用,该映射将使用
名称
(因为它是主键)创建映射表。所涉及的字符串类型使其速度非常慢(长度>128个字符,通常只在最后几个字符中有所不同)。为了加快速度,我想为连接创建一个
auto_increment
列(我使用的是MySQL),同时仍然能够让nhibernate使用
Name
-列来排序我的对象的唯一性

下面是一个它看起来像什么的例子。实际上,这些物体要大得多

class MyObject{
  public String Name;
  public String Value;
}
//Mapping
Id(x => x.Name)
  .Length(255)
  .Unique();
Map(x => x.Value);
这正是我们想要的。如果我向表中添加一个新的
MyObject
,nhibernate将首先进行选择,以查看表中是否已存在具有相同
名称的记录

我有一个
ObjectHolder
,它有一组
MyObject

class ObjectHolder{
  public UInt64 Id;
  public ICollection<MyObject> MyObjects;
}
//Mapping
Id(x => x.Id)
  .GeneratedBy.Native();
HasManyToMany(x => x.MyObjects)
  .AsSet()
  .Cascade.SaveUpdate();
这将创建一个自动增量列并将其用于映射表,但是现在它将不再正确检查是否已存在具有相同
名称的记录,这将导致重复条目异常

我是否可以告诉nhibernate检查
Name
列而不是id,或者对
id
-列进行注释,使其仅用作外键,而不用作其他键?我必须修改多个映射吗


编辑:如果我不得不使用复合ID,情况似乎更糟。所有id属性都保存了两次,一次保存在对象本身中,一次保存在映射中,这会增加大量的时间和存储空间开销。

如果您错误地看待这个问题,NH不应该检查它是否已经存在。你应该知道它是否已经存在

检查名称是否唯一应该是验证和业务逻辑的一部分。因此,在尝试保存之前,您应该检查是否使用了该名称

如果您自己访问数据库,则可以处理约束冲突。然而,NHibernate不支持这一点,因为它会使批处理复杂化。也就是说,在刷新事务时将保存批处理,这将是引发错误的点,而不是保留实体的点。所以NH能做的唯一明智的事情就是回滚整个事务并抛出一个错误


基本上,数据库约束只是防止无效数据的最终故障保护,而不是检查业务规则所依赖的东西。

如果您以错误的方式看待这个问题,NH不应该检查它是否已经存在。你应该知道它是否已经存在

检查名称是否唯一应该是验证和业务逻辑的一部分。因此,在尝试保存之前,您应该检查是否使用了该名称

如果您自己访问数据库,则可以处理约束冲突。然而,NHibernate不支持这一点,因为它会使批处理复杂化。也就是说,在刷新事务时将保存批处理,这将是引发错误的点,而不是保留实体的点。所以NH能做的唯一明智的事情就是回滚整个事务并抛出一个错误


基本上,数据库约束只是防止无效数据的最终故障保护,而不是检查业务规则所依赖的东西。

我认为(希望)您误解了。名称是其对象的唯一ID。根据设计,该名称已经存在,具有相同名称的对象表示相同的对象。在这种情况下,我希望nhibernate更新对象,然后保存/更新保存多个关系的父对象。我使用ORM正是因为我不想用通常的select,if exists update,else insert来处理所有太多的集合;递归地循环遍历我的整个层次结构。我只希望nhibernate使用不同的列(对于mysql,由于自动增量,它必须是主键)来进行数据库连接,而不是其他。对,但是如果你告诉NH这是id列,那么就NH而言,这是id,而不是名称。您可以将name设置为自然键,但这不会有多大变化。主要的是NH不应该通过数字id或名称来检查您是否已经存在某些东西。由于您使用的是auto_increment列,您会立即看到错误,但是如果您使用的是say hilo,NH不会尝试将对象保存到DB,直到您提交事务,此时它会在一个批中保存所有更改(当DBMS支持时)。我想(希望)您误解了。名称是其对象的唯一ID。根据设计,该名称已经存在,具有相同名称的对象表示相同的对象。在这种情况下,我希望nhibernate更新对象,然后保存/更新保存多个关系的父对象。我使用ORM正是因为我不想用通常的select,if exists update,else insert来处理所有太多的集合;递归地循环遍历我的整个层次结构。我只希望nhibernate使用不同的列(对于mysql,由于自动增量,它必须是主键)来进行数据库连接,而不是其他。对,但是如果你告诉NH这是id列,那么就NH而言,这是id,而不是名称。您可以将name设置为自然键,但这不会有多大变化。主要的是NH不应该通过数字id或名称来检查您是否已经存在某些东西。由于您使用的是auto_increment列,您会立即看到错误,但如果您使用的是say hilo,NH不会尝试将对象保存到DB,直到您提交事务,此时它将在单个批中保存所有更改(DBMS支持时)。
class MyObject{
  public UInt64 Id;
  public String Name;
  public String Value;
}
//Mapping
Id(x => x.Id)
  .GeneratedBy.Native();
Map(x => x.Name)
  .Length(255)
  .Unique();
Map(x => x.Value);