3

マッピングを表示することから始めましょう。

親:

<bag name="Communicatiekanalen" table="COMMUNICATIEKANAAL" inverse="true" cascade="delete" lazy="true" >
        <key column="SEK_PROFIEL"/>
        <one-to-many class="Crm.Hibernate.Communicatiekanaal,Crm.Hibernate" />
</bag>

子:

<many-to-one name="SekProfiel" column="SEK_PROFIEL" class="Crm.Hibernate.Profiel,Crm.Hibernate" />

つまり、プロファイルには多くの通信チャネルを含めることができます。

UI (ユーザー インターフェイス[ASP.NET Webforms] ) で、次のイベントが発生します (通信チャネルが関連付けられたプロファイルを削除します)。

    var profielDao = CrmConfiguration.GetDaoFactory().GetProfielDao();
    var profiel = profielDao.GetById(2194, true); //lets say '2194' is an ID that exists
    profielDao.Delete(profiel);

(DaoFactory は 1 つのプロジェクト ファイルにあり、UI は ASP.NET Web サイトです)

このコードは機能します。

重要:コードは NHibernate の「open-session-in-view」パターンを使用しています。

同じコードを起動するサービスの実装があります (通信チャネルでプロファイルを削除します)。いくつかのコード...

            var daof = CrmConfiguration.GetDaoFactory();
            CrmSettings.Instance.UserID = user;
            var profielDao = daof.GetProfielDao();

            profielDao.BeginTransaction();
            var profiel = profielDao.GetById(CrmEntitiesToHibernate.ParseStringToId(profileId), true);
            profielDao.Delete(profiel);
            profielDao.EndTransaction();

「EndTransaction()」は「コミット」を行います。このコードを「単体テスト」でテストします。

    [TestMethod]
    public void TestDeleteProfile()
    {
        //Getting a valid NEW profile
        var profile = GetSecundaryProfile();
        //Adding a communication channel to the profile
        CrmClient.AddCommunicationChannelForProfile(GetPlainCommunicationChannel(), profile.Id, CurrentUserId);
        //Calling the 'delete profile' method on the service --> FAIL - no cascade
        CrmClient.DeleteProfile(profile.Id, CurrentUserId);
    }

このコードは失敗します。次のエラーが私を悩ませています:

DELETE ステートメントは、REFERENCE 制約 "R2_PROFIEL" と競合しました。データベース「CRM_ontw」、テーブル「dbo.COMMUNICATIEKANAAL」、列「SEK_PROFIEL」で競合が発生しました。ステートメントは終了されました。

これは、カスケードがまったく発生しなかったことを意味します。UIから実行すると機能しますが、「サービスの実装」から実行すると失敗します。私に役立つアイデアや提案はありますか?

前もって感謝します


編集:次の一般的なコードはオブジェクトを削除します

    public void Delete(T entity)
    {
        try
        {
            OnDelete(entity);
        }
        catch (Exception)
        {
            SessionManager.Instance.RollbackTransactionOn(SessionFactoryConfigPath);
            throw;
        }
        session.Delete(entity);
    }

を設定しall-delete-orphanても問題は解決しません。

4

2 に答える 2

2

問題を見つけました。NHibernateの「open-session-in-view」パターンは、データベースへの変更をコミットした後にセッションを閉じます(したがって、要求が終了すると、セッションは閉じられます)。

        finally
        {
            // No matter what happens, make sure all the sessions get closed
            foreach (SessionFactoryElement sessionFactorySettings in openSessionInViewSection.SessionFactories)
            {
                SessionManager.Instance.CloseSessionOn(sessionFactorySettings.FactoryConfigPath);
            }
        }

しかし、EndTransaction()サービス側での私の実装はそうではありませんでした。

そこで、いくつかの調整を加えて、このEndTransaction()メソッドを作成しました。

public void EndTransaction()
{
    try
    {
        SessionManager.Instance.CommitTransactionOn(SessionFactoryConfigPath);
    }
    finally
    {
        SessionManager.Instance.CloseSessionOn(SessionFactoryConfigPath);
    }
}
于 2011-03-01T13:54:20.537 に答える
0

に設定cascade="delete"してみてくださいcascade="all-delete-orphan"

また、両方のインスタンスで、親が同じインスタンスによって読み取られ、保存ISessionされていることを確認してください。誰かがコメントしたように、.Delete()メソッドの実装を確認する必要があります。

于 2011-02-28T19:13:17.567 に答える