0

我正在开发一个将数据传回数据库的客户端应用程序。客户端可以创建 PlaylistItem 类型的对象。在创建 PlaylistItem 时,我不会等待数据库以生成的 ID 进行响应。相反,我让客户端生成 ID,但将 PlaylistItem 写入数据库,PK 为 { PlaylistID, PlaylistItemID }。PlaylistID 由服务器生成。在与 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 抛出异常并显示错误消息“Invalid index n for this SqlParameterCollection with Count=n”。我知道当 hbm.xml 文件中有重复声明时会出现这种情况。据我了解,这是因为我将 PlaylistId 定义为键属性,并且再次以多对一关系定义。

我在这里有什么选择?我很困惑。

4

1 回答 1

1

您可以使用 akey-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...
}
于 2013-04-03T08:02:01.460 回答