2

我有一个 User 类,它与 PlaylistCollection 类具有一对多的关系。同样,PlaylistCollection 与 Playlist 类具有一对多的关系。

我想创建一个新的用户对象并将其保存到数据库中。作为副作用,我希望一个新的 PlaylistCollection 和一个新的 Playlist 也被写入数据库。当我调用 commit -- NHibernate 抛出异常:

exec sp_executesql N'INSERT INTO [Playlists] (CollectionId, Title, Position, Id) VALUES (@p0, @p1, @p2, @p3)',N'@p0 uniqueidentifier,@p1 nvarchar(4000),@p2 int,@p3 uniqueidentifier',@p0='00000000-0000-0000-0000-000000000000',@p1=N'New Playlist',@p2=0,@p3='CD593D78-5300-434E-B256-6271D4A60915'

The INSERT statement conflicted with the FOREIGN KEY constraint "FK66D0C3A319AEA85C". The conflict occurred in database "StreamusTest", table "dbo.PlaylistCollections", column 'Id'.

如果我省略给我的 PlaylistCollection 一个初始的 Playlist 对象,则不会发生此错误。我可以将具有 PlaylistCollection 的用户写入数据库,但不是用户 - > PlaylistCollection - > 播放列表。

我的映射:

  <class name="User" table="[Users]" lazy="false">
    <id name="Id" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid" />
    </id>

    <property name="Name" />

    <bag name="PlaylistCollections" cascade="all-delete-orphan" >
      <key column="UserId" />
      <one-to-many class="PlaylistCollection" />
    </bag>
  </class>

  <class name="PlaylistCollection" table="[PlaylistCollections]" lazy="false" >
    <id name="Id" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid" />
    </id>

    <property name="Title" not-null="true" />

    <bag name="Playlists" cascade="all-delete-orphan" >
      <key column="CollectionId" />
      <one-to-many class="Playlist" />
    </bag>
  </class>

  <class name="Playlist" table="[Playlists]" lazy="false" >
    <id name="Id" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid" />
    </id>

    <property name="CollectionId" not-null="true" />
    <property name="Title" not-null="true" />
    <property name="Position" not-null="true" />

    <bag name="Items" cascade="all-delete-orphan" >
      <key column="PlaylistId" />
      <one-to-many class="PlaylistItem" />
    </bag>
  </class>

和实体构造函数/辅助方法:

public User()
{
    Name = string.Empty;
    PlaylistCollections = new List<PlaylistCollection>
        {
            new PlaylistCollection("New Playlist Collection")
        };
}

public PlaylistCollection()
{
    Id = Guid.Empty;
    UserId = Guid.Empty;
    Title = string.Empty;
    Playlists = new List<Playlist>();

    //  A collection should always have at least one Playlist.
    CreatePlaylist();
}

public PlaylistCollection(string title) 
    : this()
{
    Title = title;
}


public Playlist()
{
    Id = Guid.Empty;
    CollectionId = Guid.Empty;
    Title = string.Empty;
    Position = -1;
    Items = new List<PlaylistItem>();
}
public Playlist CreatePlaylist()
{
    string playlistTitle = string.Format("New Playlist {0:D4}", Playlists.Count);
    var playlist = new Playlist(playlistTitle);
    return AddPlaylist(playlist);
}

public Playlist AddPlaylist(Playlist playlist)
{
    if (Id != Guid.Empty)
    {
        playlist.CollectionId = Id;
    }

    playlist.Position = Playlists.Count;

    Playlists.Add(playlist);
    return playlist;
}

最后,这是失败的方法:

/// <summary>
///     Creates a new User and saves it to the DB. As a side effect, also creates a new, empty
///     PlaylistCollection (which has a new, empty Playlist) for the created User and saves it to the DB.
/// </summary>
/// <returns>The created user with a generated GUID</returns>
public User CreateUser()
{
    User user;
    try
    {
        NHibernateSessionManager.Instance.BeginTransaction();

        user = new User();
        user.ValidateAndThrow();
        UserDao.Save(user);

        NHibernateSessionManager.Instance.CommitTransaction();
    }
    catch (Exception exception)
    {
        Logger.Error(exception);
        NHibernateSessionManager.Instance.RollbackTransaction();
        throw;
    }

    return user;
}

显然,问题在于 Playlist 对象正在尝试使用 Guid.Empty 的 CollectionId 来保存自己。它应该尝试使用在保存 PlaylistCollection 时生成的任何内容的 CollectionId 来保存自己。

更新:这可行,但显然是被迫的。我该如何改进它?

// 播放列表类内部:

[DataMember(Name = "collectionId")]
public Guid CollectionId
{
    get { return Collection.Id; }
    set { Collection.Id = value; }
}

public PlaylistCollection Collection { get; set; }

这样做可以让我返回我的 collectionId 并且 NHibernate 现在已经正确地找出了映射......但对我来说似乎仍然有点强迫。

4

0 回答 0