0

識別子として null 許容フィールドを持つ同じテーブルから読み取る 2 つの結合されたサブクラスがあります。次のようなサブセレクトを使用して、2 つのエンティティを読み取ることができました。

<joined-subclass name="EntityA"
    table="t_entity"
    subselect="SELECT * FROM t_entity WHERE t_entity.discriminator is not null">
  <key column="t_uid"></key>
    <!-- more mapping -->
</joined-subclass>

<joined-subclass name="EntityB"
    table="t_entity"
    subselect="SELECT * FROM t_entity WHERE t_entity.discriminator is null">
  <key column="t_uid"></key>
    <!-- more mapping -->
</joined-subclass>

すべて問題ありませんが、2 つのエンティティのいずれかを削除しようとすると、構文エラーが発生します。

NHibernate.Exceptions.GenericADOException was unhandled
  HResult=-2146232832
  Message=could not delete: [EntityA#27]
  [SQL: DELETE FROM ( SELECT * 
        FROM t_entity 
        WHERE t_entity.discriminator is not null ) WHERE t_uid = ?]
Source=NHibernate

null 許容フィールドによって同じテーブルからエンティティを区別する方法について、より良いアイデアはありますか?

スタック トレースは次のとおりです。

   at NHibernate.Persister.Entity.AbstractEntityPersister.Delete(Object id, Object version, Int32 j, Object obj, SqlCommandInfo sql, ISessionImplementor session, Object[] loadedState)
   at NHibernate.Persister.Entity.AbstractEntityPersister.Delete(Object id, Object version, Object obj, ISessionImplementor session)
   at NHibernate.Action.EntityDeleteAction.Execute()
   at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
   at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
   at NHibernate.Engine.ActionQueue.ExecuteActions()
   at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
   at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
   at NHibernate.Impl.SessionImpl.Flush()
   at NHibernate.Transaction.AdoTransaction.Commit()
   at Nephila.Toolkit.Data.Implementations.Transaction.Commit() in C:\Projects\Git\nephilaapiTFS\Toolkit\Nephila.Toolkit.Data.Implementations\Transaction.cs:line 48
   at Nephila.Dashboard.ServiceLayer.WidgetRegistrationService.UnregisterWidget(Widget widget) in C:\Projects\Git\nephilaapiTFS\Dashboard\Nephila.Dashboard.ServiceLayer\WidgetRegistrationService.cs:line 206
   at Nephila.Dashboard.WidgetRegistrationConsole.Instance.UnregisterWidget(String widgetUrlName) in C:\Projects\Git\nephilaapiTFS\Nephila.Dashboard.WidgetRegistrationConsole\Program.cs:line 254
   at Nephila.Dashboard.WidgetRegistrationConsole.Instance.Display(String[] args) in C:\Projects\Git\nephilaapiTFS\Nephila.Dashboard.WidgetRegistrationConsole\Program.cs:line 97
   at Nephila.Dashboard.WidgetRegistrationConsole.Program.Main(String[] args) in C:\Projects\Git\nephilaapiTFS\Nephila.Dashboard.WidgetRegistrationConsole\Program.cs:line 19
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

   InnerException: System.Data.SqlClient.SqlException
   HResult=-2146232060
   Message=Incorrect syntax near '('.
   Incorrect syntax near the keyword 'WHERE'.
   Statement(s) could not be prepared.
   Source=.Net SqlClient Data Provider
   ErrorCode=-2146232060
   Class=15
   LineNumber=1
   Number=102
   Procedure=""
   Server=(local)
   State=1
   StackTrace:
        at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
        at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
        at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
        at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
        at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite)
        at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
        at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
        at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
        at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
        at NHibernate.Persister.Entity.AbstractEntityPersister.Delete(Object id, Object version, Int32 j, Object obj, SqlCommandInfo sql, ISessionImplementor session, Object[] loadedState)
4

2 に答える 2

1

副選択を使用する代わりに、ディスクリミネーターの式を使用して、ディスクリミネーターベースの継承マッピングを使用できます。

<class name="BaseEntity" table="t_entity">
   <!-- base id and properties mapping -->

  <discriminator formula="CASE discriminator is not null 
                          WHEN true THEN 'EntityA' 
                          ELSE 'EntityB' 
                          END" />

  <subclass name="EntityA" discriminator-value="EntityA">
    <!-- more mapping -->
  </subclass>

  <subclass name="EntityB" discriminator-value="EntityB">
    <!-- more mapping -->
  </subclass>
</class>

その後、エンティティを削除できるようになります。

于 2013-03-16T17:25:30.913 に答える
0

私にとっての答えは、2 つのエンティティを 2 つの異なるテーブルに分割して、共通のベース テーブルに共通のフィールドを保持し、各子テーブルに独自の貴重な情報を設定することでした。

<joined-subclass name="BaseEntity"
    table="t_entity_base"
    abstract="true">
      <key column="t_uid"></key>
        <!-- common mapping -->

    <joined-subclass name="EntityA"
        table="t_entity_a">
      <key column="t_uid"></key>
      <!-- specific fields, i.e.: -->
      <property name="discriminator" column="discriminator"/>

    </joined-subclass>


    <joined-subclass name="EntityB"
        table="t_entity_b">
      <key column="t_uid"></key>

    </joined-subclass>

</joined-subclass>

ご協力いただきありがとうございます。

于 2013-03-17T23:39:43.427 に答える