I created a WCF service in Visual Studio, and as said in the title, it can't access a SQL Server database whilst a console project, built with more or less the same code, can.
Here is the IService
interface:
[ServiceContract]
public interface IService
{
[OperationContract]
Supermarche getSupermarche();
}
Here is the implementation of the method:
public class Service : IService
{
public Supermarche getSupermarche()
{
//récupération en base
Model.Supermarche supermarche = null;
using (var ctx2 = new MarketContext("sqlserverPersonalId"))
{
supermarche = ctx2.Supermarches.First<Model.Supermarche>();
}
return supermarche;
//return new Supermarche() { SupermarcheId = 5, Magasins = null };
}
}
With the last return statement, the app ClientTestWCF
is able to invoke the getSupermarche()
method and it gets the correct result. Then I guess the problem comes from the database access.
This database is used with Entity Framework; as there seems to be no problem with that (as the last return above works) I won't show it here. Please just notice that I adorned the classes with [DataContract]
and [DataMember]
.
The service is published in IIS, those of Windows and not the integrated one.
Here is the Web.config file (in the Service project):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false"/>
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="false" targetFramework="4.7.2"/>
<httpRuntime targetFramework="4.7.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service">
<endpoint address=""
binding="basicHttpBinding"
contract="IService"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080"/>
</baseAddresses>
</host>
</service>
</services>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
<handlers>
<add name="serviceHandler" verb="*" path=".svc"
type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
</handlers>
</system.webServer>
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
</providers>
</entityFramework>
<connectionStrings>
<add name="sqlserver"
connectionString="Data Source=xxx\SQLEXPRESS;Integrated Security=True;Connect Timeout=90;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;Initial Catalog=Market"
providerName="System.Data.SqlClient"/>
<add name="sqlserverPersonalId"
connectionString="Data Source=xxx\SQLEXPRESS;Initial Catalog=Market;User ID=xxx;Password=xxx;Connect Timeout=90;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
EDIT:
I forgot the error, got in the client Microsoft test app:
Échec de l'appel du service. Causes possibles : le service est peut être hors ligne ou inaccessible ; la configuration côté client ne correspond pas au proxy ; le proxy existant n'est pas valide. Reportez-vous à la trace de la pile pour plus de détails. Vous pouvez tenter une récupération en démarrant un nouveau proxy, en restaurant la configuration par défaut ou en actualisant le service.
it means:
Service call failed.the service can be unreachable, the existing proxy is not valid.You can try to create a new proxy, by restoring the default configuration or by updating the service.
Here is the stack trace:
Une erreur s'est produite lors de la réception de la réponse HTTP à http://localhost/market8/Service.svc. La raison peut en être que la liaison de point de terminaison de service n'utilise pas le protocole HTTP. Cela peut également être dû au fait qu'un contexte de requête HTTP a été ignoré par le serveur (peut-être à cause de l'arrêt du service). Pour plus d'informations, consultez les journaux du serveur.
it means:
There was an error at the http answer reception for the http://localhost/market8/Service.svc call, the endpoint may not use the HTTP protocol, or the HTTP request context may be ignored by the server (cause : service stopped?).
Server stack trace: à System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) à System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) à System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) à System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)Exception rethrown at [0]: à System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) à System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) à IService.getSupermarche() à ServiceClient.getSupermarche()
Inner Exception: La connexion sous-jacente a été fermée : Une erreur inattendue s'est produite lors de la réception. à (it means : the underlying connection was closed : an unexpected error happened at the reception)
System.Net.HttpWebRequest.GetResponse() à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception: Impossible de lire les données de la connexion de transport : Une connexion existante a dû être fermée par l’hôte distant.
(it means : no way to read the datas of the transport connection : a existing connection had to be closed)à System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) à System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) à System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception: Une connexion existante a dû être fermée par l’hôte distant
(it means : a remote connection had to be closed by the remote host) à System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) à System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
The service is deployed to IIS.
EDIT Here is the code for the main() method in the console project:
static void Main(string[] args)
{
using (var ctx = new MarketContext("sqlserver"))
{
new MyDataInitializer().InitializeDatabase(ctx);
//var produitMagasin = new ProduitMagasin() { Nom = "Pommes", Quantite = 10 };
//ctx.ProduitsMagasin.Add(produitMagasin);
//var rayon1 = new Rayon() { Nom = "Fruits & Légumes", Produits = new List<ProduitMagasin> { produitMagasin } };
//ctx.Rayons.Add(rayon1);
var produitMagasin1 = new ProduitMagasin() { Nom = "Pommes", Quantite = 10 };
var produitMagasin2 = new ProduitMagasin() { Nom = "Poires", Quantite = 5 };
var rayon1 = new Rayon() { Nom = "fruits & légumes", Produits = new List<ProduitMagasin>() { produitMagasin1, produitMagasin2 } };
var magasin1 = new Magasin() { Rayons = new List<Rayon>() { rayon1 } };
var supermarche1 = new Supermarche() { Magasins = new List<Magasin> { magasin1 } };
ctx.Supermarches.Add(supermarche1);
ctx.SaveChanges();
Console.WriteLine("Programme exécuté");
Console.ReadLine();
}
}
I use "sqlserver" as the connectionString, so I changed the service connection string to "sqlserver" too but it didn't help.
EDIT It is worth noticing that when the getSupermarche() method returns an artificial Supermarche object, there is no error and I can get the expected result. So the problem seems to come from the database access, not from the http configuration (unless both are linked but I don't think so).
Linq problem?
Here are the references in the console project:
and here are the references of the service project:
I didn't noticed a problem thought.