我有一个简单的类,它有一个Name
成员,用于唯一标识一个实例。该类在ManyToMany映射中引用,该映射将使用Name
(因为它是主键)来创建映射表。所涉及的字符串类型使其非常缓慢(长度> 128个字符,通常仅在最后几个不同)。为了加速它,我想创建一个auto_increment
列(我使用MySQL)进行连接,同时仍然可以使用Name
列对nhibernate进行唯一性排序。nhibernate可以检查唯一的约束,而不是主键
下面是它的样子的一个例子。事实上,这些物体要大得多。
class MyObject{
public String Name;
public String Value;
}
//Mapping
Id(x => x.Name)
.Length(255)
.Unique();
Map(x => x.Value);
这按预期工作。如果我在表格中添加一个新的MyObject
,nhibernate将首先进行选择,以查看表格中是否已经存在具有相同Name
的记录。
我有了一套MyObject
class ObjectHolder{
public UInt64 Id;
public ICollection<MyObject> MyObjects;
}
//Mapping
Id(x => x.Id)
.GeneratedBy.Native();
HasManyToMany(x => x.MyObjects)
.AsSet()
.Cascade.SaveUpdate();
这将创建一个使用ObjectHolder.Id
和MyObject.Name
的映射,这是一个缓慢ObjectHolder
。我希望MyObject
有一个自动生成的Id列,只用于映射表,但不能用于nhibernate对主键进行select-to-see-if-it-exists检查。
我已经改变了映射到
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);
这将创建一个AUTO_INCREMENT列,并用它的映射表,但它现在不再是正确的检查,如果用相同的Name
的记录已经存在,这会导致重复的输入异常。
我可以告诉nhibernate检查Name
列而不是id,或者注释Id
- 列,因此它只用作外键,但没有别的?我必须修改manyToMany映射吗?
编辑:如果我不得不使用组合ID,那就更糟糕了。所有的id属性都保存了两次,一次在对象本身中,一次在映射中,这会增加巨大的时间和存储空间开销。
我想(希望)你误会了。该名称是该对象的唯一ID。该名称已经存在是由设计决定的,具有相同名称的对象表示相同的对象。在这种情况下,我希望nhibernate更新对象,然后保存/更新保存manyToMany关系的父项。我正在使用ORM,因为我不想用通常的select来处理所有manyToMany集合,如果存在update,否则插入;递归循环遍历整个层次结构。 – Darcara
我只想让nhibernate使用不同的列(对于mysql必须是由于auto_increment产生的主键)来执行数据库连接,而不是其他任何操作。 – Darcara
对,但如果你告诉NH是id列,那么就NH而言,关心的是id,而不是名称。您可以将名称设置为自然键,但这并没有太大改变。最主要的是NH不应该真的在检查是否已经存在的东西,通过数字ID或名称。由于您使用的是auto_increment列,因此您会立即看到该错误,但如果您使用的是hilo,则NH不会尝试将对象保存到数据库,直到您提交事务,此时它将保存所有更改在一个批次中(当由DBMS支持时)。 –