带有 EF 的 ADO.NET 数据服务实现每个具体类型表 (TPCT) 继承

发布于 2024-09-25 23:06:00 字数 7746 浏览 2 评论 0原文

我正在使用一个在多个表中具有重复数据的 SQL 数据源。我无法控制数据库。对于我的项目,我创建了一个 EF 模型和一个公开它的 ADO.NET 数据服务(使用 VS 2008)。我还有一个使用该服务的 .NET 客户端应用程序。

现在,这些数据库表有大量公共字段,我需要在向服务发送插入请求之前在客户端中对这些字段进行水化。因此,为了避免重复代码,我在 EF 模型中创建了一个抽象基类,并将所有公共属性放入其中。该基类的实体集名称是OrderEntries。从它继承的实体之一称为OEORDH。它映射到数据库表。为了公开此实体,我创建了一个 WebGet 服务方法,因为查询使用 OfType 方法,该方法不支持到 ATOM 的转换;因此我不能在我的客户端中使用它。方法如下:

<WebGet()> _
Public Function Orders() As IQueryable(Of OEORDH)
    Dim results = From x In Me.CurrentDataSource.OrderEntries.OfType(Of OEORDH)()
    Return results
End Function

当我在浏览器中访问此方法时(http://localhost:1187/MyService.svc/Orders),我收到一个非常通用的错误:

<link rel="self" title="Orders" href="Orders" />
  <m:error>
    <m:code></m:code>
    <m:message xml:lang="en-US">An error occurred while processing this request.</m:message>
  </m:error>

但我知道查询被调用,而且,当我在调试中观察“本地”窗口,我发现它返回了正确的对象集合。其他查询非继承实体的 Web 方法也可以正常工作。怎么了?

更新 我听从了 Steve 的建议,将 IncludeExceptionDetailInFaults 设置为 true。我还将 UseVerboseErrors 设置为 true。跟踪日志现在显示抛出的异常是 System.ServiceModel.CommunicationObjectAbortedException,它仍然非常通用。我在网上搜索过,但没有找到任何具体的信息。该消息是: 通信对象 System.ServiceModel.Channels.TransportReplyChannelAcceptor+TransportReplyChannel 无法用于通信,因为它已被中止。这是堆栈内容:

System.ServiceModel.Channels.CommunicationObject.ThrowIfAborted()
System.ServiceModel.Channels.InputQueueChannel`1.EndDequeue(IAsyncResult result, TDisposable&amp; item)
System.ServiceModel.Channels.ReplyChannel.EndTryReceiveRequest(IAsyncResult result, RequestContext&amp; context)
System.ServiceModel.Dispatcher.ReplyChannelBinder.EndTryReceive(IAsyncResult result, RequestContext&amp; requestContext)
System.ServiceModel.Dispatcher.ErrorHandlingReceiver.EndTryReceive(IAsyncResult result, RequestContext&amp; requestContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
System.ServiceModel.Channels.InputQueue`1.Shutdown(CommunicationObject communicationObject)
System.ServiceModel.Channels.InputQueueChannel`1.OnClosing()
System.ServiceModel.Channels.CommunicationObject.Abort()
System.ServiceModel.Dispatcher.ReplyChannelBinder.Abort()
System.ServiceModel.Channels.ServiceChannel.OnAbort()
System.ServiceModel.Channels.CommunicationObject.Abort()
System.Data.Services.DelegateBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
System.ServiceModel.Channels.HttpStreamMessageEncoderFactory.HttpStreamMessageEncoder.WriteMessage(Message message, Stream stream)
System.ServiceModel.Channels.HttpStreamMessageEncoderFactory.HttpStreamMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message)
System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
System.ServiceModel.Channels.RequestContextBase.Reply(Message message)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc)
System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(MessageRpc&amp; rpc, Boolean isOperationContextSet)
System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
System.ServiceModel.PartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

I am working with a SQL data source that has duplicate data in multiple tables. I have no control over the database. For my project, I've created an EF model and an ADO.NET data service (using VS 2008) that exposes it. I also have a .NET client application that consumes the service.

Now, these db tables have a large number of fields common, which I need to hydrate in my client before sending an insert request to the service. So, wanting to avoid repetitive code, I created an abstract base class in my EF model and put all the common properties in it. The entity set name of this base class is OrderEntries. One of the entities inheriting from it is called OEORDH. It maps to a db table. To expose this entity, I created a WebGet service method because the query uses OfType method, which has no supported translation to ATOM; hence I can't use it in my client. Here's the method:

<WebGet()> _
Public Function Orders() As IQueryable(Of OEORDH)
    Dim results = From x In Me.CurrentDataSource.OrderEntries.OfType(Of OEORDH)()
    Return results
End Function

When I access this method in the browser (http://localhost:1187/MyService.svc/Orders), I get a very generic error back:

<link rel="self" title="Orders" href="Orders" />
  <m:error>
    <m:code></m:code>
    <m:message xml:lang="en-US">An error occurred while processing this request.</m:message>
  </m:error>

But I know that the query gets called, and moreover, when I watch the Locals window in debug, I see that it returns the right collection of objects. Other web methods that query non-inheriting entities work just fine. What is wrong?

UPDATE
I followed Steve's advice and set IncludeExceptionDetailInFaults to true. I also set UseVerboseErrors to true. The trace log now shows that the exception being thrown is System.ServiceModel.CommunicationObjectAbortedException, which is still pretty generic. I searched the web, but didn't find anything concrete. The message is: The communication object, System.ServiceModel.Channels.TransportReplyChannelAcceptor+TransportReplyChannel, cannot be used for communication because it has been Aborted. Here's the stack content:

System.ServiceModel.Channels.CommunicationObject.ThrowIfAborted()
System.ServiceModel.Channels.InputQueueChannel`1.EndDequeue(IAsyncResult result, TDisposable& item)
System.ServiceModel.Channels.ReplyChannel.EndTryReceiveRequest(IAsyncResult result, RequestContext& context)
System.ServiceModel.Dispatcher.ReplyChannelBinder.EndTryReceive(IAsyncResult result, RequestContext& requestContext)
System.ServiceModel.Dispatcher.ErrorHandlingReceiver.EndTryReceive(IAsyncResult result, RequestContext& requestContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
System.ServiceModel.Channels.InputQueue`1.Shutdown(CommunicationObject communicationObject)
System.ServiceModel.Channels.InputQueueChannel`1.OnClosing()
System.ServiceModel.Channels.CommunicationObject.Abort()
System.ServiceModel.Dispatcher.ReplyChannelBinder.Abort()
System.ServiceModel.Channels.ServiceChannel.OnAbort()
System.ServiceModel.Channels.CommunicationObject.Abort()
System.Data.Services.DelegateBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
System.ServiceModel.Channels.HttpStreamMessageEncoderFactory.HttpStreamMessageEncoder.WriteMessage(Message message, Stream stream)
System.ServiceModel.Channels.HttpStreamMessageEncoderFactory.HttpStreamMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message)
System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
System.ServiceModel.Channels.RequestContextBase.Reply(Message message)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(MessageRpc& rpc, Boolean isOperationContextSet)
System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
System.ServiceModel.PartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文