我有一个通过 EntityFramework 与 SQLExpress DB 通信的项目。现在我想在系统中添加一个 WCF 层。
这是我在第一个版本(无 WCF)中的一些代码:
MessageService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newsletter.DAL;
using System.Data.Entity;
using System.Windows;
using System.Data.Objects.DataClasses;
namespace Newsletter.Services
{
public class MessageService
{
private NewsletterEntities _context;
public MessageService()
{
_context = new NewsletterEntities();
}
public Task AddMessageAsync(string subject,string content, bool hasAttachments, DateTime date, Sender sender, MailingList mailingList)
{
return Task.Factory.StartNew(() =>
{
Message newMessage = new Message();
newMessage.Subject = subject;
newMessage.Content = content;
newMessage.HasAttachments = hasAttachments;
newMessage.Date = date;
newMessage.Sender = sender;
newMessage.MailingList = mailingList;
_context.Messages.AddObject(newMessage);
_context.SaveChanges();
});
}
public Task EditMessageAsync(int id, DateTime date, string content, MailingList mailingLists, Sender sender, string subject, bool hasAttachments)
{
return Task.Factory.StartNew(() =>
{
var messageToChange = (from m in _context.Messages where id == m.MessageID select m).FirstOrDefault();
if (messageToChange != null)
{
messageToChange.Date = date;
messageToChange.Content = content;
messageToChange.MailingList = mailingLists;
messageToChange.Sender = sender;
messageToChange.Subject = subject;
messageToChange.HasAttachments = hasAttachments;
_context.SaveChanges();
}
});
}
public Task<List<Message>> GetAllMessagesAsync()
{
return Task.Factory.StartNew(() => _context.Messages.ToList());
}
public Task<List<MailingList>> GetAllMailingListsAsync()
{
return Task.Factory.StartNew(() => _context.MailingLists.ToList());
}
public Task<List<Sender>> GetAllSendersAsync()
{
return Task.Factory.StartNew(() => _context.Senders.ToList());
}
public Task DeleteMessageAsync(Message message)
{
return Task.Factory.StartNew(() =>
{
MailingList mailinglist = message.MailingList;
mailinglist.Message.Remove(message);
_context.Messages.DeleteObject(message);
_context.SaveChanges();
});
}
}
}
我想从一些简单的事情开始,以检查我是否知道大体上发生了什么。我创建了 WCF 服务库项目。我有IMessageService.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Newsletter.Common;
namespace WcfServiceLibrary
{
[ServiceContract]
public interface IMessageService
{
[OperationContract]
void DeleteMessage(MessageDTO message);
}
}
和MessageService.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Newsletter.Common;
using Newsletter.DAL;
using System.Data.Entity;
using System.Data.Objects.DataClasses;
namespace WcfServiceLibrary
{
public class MessageService : IMessageService
{
private NewsletterEntities _context;
public MessageService()
{
_context = new NewsletterEntities();
}
public void DeleteMessage(MessageDTO messageDTO)
{
MailingList mailinglist = (from m in _context.MailingLists where m.MailingListID == messageDTO.MailingListID select m).FirstOrDefault();
Message message = (from m in _context.Messages where m.MessageID == messageDTO.MessageID select m).FirstOrDefault();
mailinglist.Message.Remove(message);
_context.Messages.DeleteObject(message);
_context.SaveChanges();
}
}
}
最后MessageDTO.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Newsletter.Common
{
public class MessageDTO
{
public int MessageID { get; set; }
public String Subject { get; set; }
public String Content { get; set; }
public bool HasAttachments { get; set; }
public DateTime Date { get; set; }
public int SenderID { get; set; }
public int MailingListID { get; set; }
}
}
我将其标记为启动项目并使用 WCF 测试客户端进行了试用。DeleteMessage()
我用一些对象调用该方法,MessageID = 1
并且MailingList = 5
- 这些是我的数据库中特定记录的值。这就是我收到错误的关键点 - 来自 DAL 的未处理异常:
The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid.
并在停止调试器后:
An error occurred while receiving the HTTP response to http://localhost:8733/WcfServiceLibrary/MessageService/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Server stack trace: at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason) at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at IMessageService.DeleteMessage(MessageDTO message) at MessageServiceClient.DeleteMessage(MessageDTO message)
Inner Exception: The underlying connection was closed: An unexpected error occurred on a receive. at System.Net.HttpWebRequest.GetResponse() at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
App.config
WCF:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="WcfServiceLibrary.MessageService">
<endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary.IMessageService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/WcfServiceLibrary/MessageService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我究竟做错了什么?一般方法可以吗?