创建具有多级子级的对象。正确保存一个级别,但不是多个级别

时间:2013-02-10 21:16:01

标签: c# .net nhibernate

我有一个User类,它与PlaylistCollection类有一对多的关系。 类似地,PlaylistCollection与播放列表类具有一对多的关系。

我想创建一个新的User对象并将其保存到数据库中。作为副作用,我希望新的PlaylistCollection和新的播放列表也可以写入数据库。当我调用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一个初始播放列表对象,则不会发生此错误。我能够将具有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来保存自己。应该尝试使用CollectionId保存自己,保存PlaylistCollection时生成的内容。

更新:这有效,但显然是强制的。我该如何改进呢?

//在播放列表类中:

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

public PlaylistCollection Collection { get; set; }

这样做可以让我返回我的collectionId,NHibernate现在已经适当地想出了映射......但似乎仍然有点强迫我。

0 个答案:

没有答案