EntityFrameworkを介してSQLExpressDBと通信するプロジェクトがあります。次に、システムに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
。これらは、DB内の特定のレコードの値です。それがエラーが発生したときのポイントです-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>
私は何が間違っているのですか?一般的なアプローチは大丈夫ですか?