2

PlaylistCollection クラスと 1 対多の関係を持つ User クラスがあります。同様に、PlaylistCollection は Playlist クラスと 1 対多の関係にあります。

新しい User オブジェクトを作成してデータベースに保存したいと考えています。副作用として、新しい 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 を持つユーザーをデータベースに書き込むことはできますが、User -> PlaylistCollection -> Playlist ではできません。

私のマッピング:

  <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 オブジェクトが CollectionId の Guid.Empty を使用して自身を保存しようとしていることです。PlaylistCollection の保存時に生成されたものの CollectionId を使用して、それ自体を保存しようとする必要があります。

更新:これは機能しますが、明らかに強制されています。どうすれば改善できますか?

// Playlist クラスの内部:

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

public PlaylistCollection Collection { get; set; }

これを行うと、自分の collectionId を返すことができ、NHibernate は現在、適切にマッピングを把握しています... しかし、それでも私には少し無理が​​あるように思えます。

4

0 に答える 0