我正在开发一个客户端应用程序,它将数据传递回数据库。客户端能够创建PlaylistItem类型的对象。在创建PlaylistItem时,我不等待数据库使用生成的ID进行响应。相反,我让客户端生成ID,但是使用PK {PlaylistID,PlaylistItemID}将PlaylistItem写入数据库。 PlaylistID由服务器生成。 I followed this approach after talking things over a bit with Jon Skeet
现在,我正试图让NHibernate的东西变得生气勃勃,但我遇到了一些相当沉重的问题。我读过的所有资源都在说,“NHibernate严重反对使用复合键。只有在你使用传统数据库时才使用它们。”我不是在处理遗留数据库,所以我认为我应该做出改变。但是,在这种情况下,我不知道我的替代方案会是什么。
这是PlaylistItem的NHibernate映射和相应的类:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Streamus" namespace="Streamus.Backend.Domain">
<class name="PlaylistItem" table="[PlaylistItems]" lazy="false" >
<composite-id>
<key-property name="Id" />
<key-property name="PlaylistId"/>
</composite-id>
<property name="Title" not-null="true" />
<many-to-one name="Playlist" column="PlaylistId"/>
</class>
</hibernate-mapping>
[DataContract]
public class PlaylistItem
{
[DataMember(Name = "playlistId")]
public Guid PlaylistId
{
get { return Playlist.Id; }
set { Playlist.Id = value; }
}
public Playlist Playlist { get; set; }
[DataMember(Name = "id")]
public Guid Id { get; set; }
// Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem.
[DataMember(Name = "title")]
public string Title { get; set; }
public PlaylistItem()
{
// Id shall be generated by the client. This is OK because it is composite key with
// PlaylistId which is generated by the server.
Id = Guid.Empty;
Title = string.Empty;
}
private int? _oldHashCode;
public override int GetHashCode()
{
// Once we have a hash code we'll never change it
if (_oldHashCode.HasValue)
return _oldHashCode.Value;
bool thisIsTransient = Equals(Id, Guid.Empty);
// When this instance is transient, we use the base GetHashCode()
// and remember it, so an instance can NEVER change its hash code.
if (thisIsTransient)
{
_oldHashCode = base.GetHashCode();
return _oldHashCode.Value;
}
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
PlaylistItem other = obj as PlaylistItem;
if (other == null)
return false;
// handle the case of comparing two NEW objects
bool otherIsTransient = Equals(other.Id, Guid.Empty);
bool thisIsTransient = Equals(Id, Guid.Empty);
if (otherIsTransient && thisIsTransient)
return ReferenceEquals(other, this);
return other.Id.Equals(Id);
}
}
NHibernate抛出异常,并显示错误消息“此SqlParameterCollection的索引号无效,且Count = n”。我明白在hbm.xml文件中有重复声明时会出现这种情况。根据我的理解,这会产生,因为我将PlaylistId定义为关键属性,并再次定义为多对一关系。
我有什么选择?我很难过。
答案 0 :(得分:1)
您可以使用key-many-to-one
代替key-property
,即
<class name="PlaylistItem" table="[PlaylistItems]" lazy="false" >
<composite-id>
<key-property name="Id" />
<key-many-to-one name="Playlist" column="PlaylistId"/>
</composite-id>
<property name="Title" not-null="true" />
</class>
然后你的班级看起来像......
[DataContract]
public class PlaylistItem
{
// Your composite key...
[DataMember(Name = "id")]
public Guid Id { get; set; }
public Playlist Playlist { get; set; }
// Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem.
[DataMember(Name = "title")]
public string Title { get; set; }
// rest of class...
}