NHibernate问题使用subselect从实体中删除
我有两个连接的子类从同一个表中读取,该表具有一个可为空的字段作为鉴别器。我已经能够使用如下子选择读取这两个实体:NHibernate问题使用subselect从实体中删除,nhibernate,domain-driven-design,nhibernate-mapping,Nhibernate,Domain Driven Design,Nhibernate Mapping,我有两个连接的子类从同一个表中读取,该表具有一个可为空的字段作为鉴别器。我已经能够使用如下子选择读取这两个实体: <joined-subclass name="EntityA" table="t_entity" subselect="SELECT * FROM t_entity WHERE t_entity.discriminator is not null"> <key column="t_uid"></key> <!--
<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>
关于如何通过一个可为空的字段从同一个表中区分实体,有更好的想法吗
这里是堆栈跟踪:
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)
您可以使用基于鉴别器的继承映射(带有鉴别器的公式,即
<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>
然后您应该能够删除实体。我的答案是将两个实体拆分到两个不同的表中,保留一个公共基表和公共字段,并在每个子表中设置它们自己的有价值的信息
<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>
感谢您的帮助。是否有内部异常跟踪?很遗憾,我不能在联接子类中使用鉴别器,但无论如何,谢谢:)您是对的,您不能在联接子类中使用鉴别器。但是您可以将它与一个子类一起使用,因为两个子类都使用同一个表,所以根据我的回答,这个表可以在基类中声明。请看Ayende的这篇非常好的文章,它解释了不同的继承策略以及它们如何映射到您的DB表。我不得不遵循另一种方法,但您的答案是有意义的。非常感谢。
<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>