简体   繁体   English

WCF 服务无法访问 SQL Server 数据库,而控制台项目可以

[英]WCF service can't access a SQL Server database while console project can

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.我在 Visual Studio 中创建了一个 WCF 服务,正如标题中所说,它无法访问 SQL Server 数据库,而使用或多或少相同代码构建的控制台项目可以。

Here is the IService interface:这是IService接口:

[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.使用最后一个 return 语句,应用程序ClientTestWCF能够调用getSupermarche()方法并获得正确的结果。 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] .请注意,我用[DataContract][DataMember]装饰了类。

The service is published in IIS, those of Windows and not the integrated one.该服务在 IIS 中发布,在 Windows 中发布,而不是在集成的 IIS 中发布。

Here is the Web.config file (in the Service project):这是 Web.config 文件(在服务项目中):

<?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:我忘记了错误,进入了客户端 Microsoft 测试应用程序:

Échec de l'appel du service. Échec de l'appel du service。 Causes possibles : le service est peut être hors ligne ou inaccessible ;可能的原因:le service est peut être hors ligne ou inaccessible ; la configuration côté client ne correspond pas au proxy ; la 配置 côté 客户端 ne 对应 pas au 代理 ; le proxy existant n'est pas valide. le 代理存在 n'est pas valide。 Reportez-vous à la trace de la pile pour plus de détails. Reportez-vous à la trace de la pile pour plus de details。 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. 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 . 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. 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). 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.倒入更多信息,请咨询 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?). http://localhost/market8/Service.svc调用的 http 应答接收出错,端点可能未使用 HTTP 协议,或者服务器可能忽略 HTTP 请求上下文(原因:服务停止? )。

Server stack trace: à System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)服务器堆栈跟踪:à 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) à 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 操作)à 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()在 [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.内部例外: 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) 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.内部例外:Impossible de lire les données de la connexion de transport : Une connexionexistante a dû être fermée par l'hôte distance。
(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) à 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 请求,Boolean userRetrievedStream,Boolean probeRead)

Inner Exception: Une connexion existante a dû être fermée par l'hôte distant内部例外:Une connexionexistante a dû être fermée par l'hôte distance
(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) (这意味着:远程主机必须关闭远程连接)à System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)à System.Net.Sockets.NetworkStream。读取(字节 [] 缓冲区,Int32 偏移量,Int32 大小)

The service is deployed to IIS.该服务已部署到 IIS。

EDIT Here is the code for the main() method in the console project:编辑这是控制台项目中 main() 方法的代码:

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.我使用“sqlserver”作为connectionString,所以我也将服务连接字符串更改为“sqlserver”,但没有帮助。

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.编辑 值得注意的是,当 getSupermarche() 方法返回一个人工 Supermarche 对象时,没有错误,我可以得到预期的结果。 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).所以问题似乎来自数据库访问,而不是来自 http 配置(除非两者都链接但我不这么认为)。

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.我没有注意到有问题的想法。

solved!解决了!

in fact, with the help of the visual debugger and the local run of the service(using WCFTestClient.exe app), I saw that the call to the context , namely事实上,在可视化调试器和服务的本地运行(使用 WCFTestClient.exe 应用程序)的帮助下,我看到了对上下文的调用,即

        using (var ctx2 = new MarketContext("sqlserver"))
        {
            var sm = ctx2.Supermarches.First();

            return sm;
        }

produces a sm variable of type : System.Data.DynamicProxies.Supermarche_xxx, and I guess it make the service crash.产生一个 sm 类型的变量:System.Data.DynamicProxies.Supermarche_xxx,我猜它会使服务崩溃。 then I searched and found it: Why is EF returning a proxy class instead of the actual entity?然后我搜索并找到了它: 为什么EF返回代理类而不是实际实体? , and then added ,然后添加

ctx2.Configuration.ProxyCreationEnabled = false;

before pulling the datas, and it worked.在提取数据之前,它起作用了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM