【问题标题】:WCF service can't access a SQL Server database while console project canWCF 服务无法访问 SQL Server 数据库,而控制台项目可以
【发布时间】:2020-01-20 10:59:53
【问题描述】:

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

这里是IService接口:

[ServiceContract]
public interface IService
{
    [OperationContract]
    Supermarche getSupermarche();
}

下面是方法的实现:

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 };
    }
}

使用最后一个 return 语句,应用程序 ClientTestWCF 能够调用 getSupermarche() 方法并获得正确的结果。那我猜问题出在数据库访问上。

此数据库与实体框架一起使用;因为这似乎没有问题(因为上面的最后一个返回有效)我不会在这里展示它。请注意,我用[DataContract][DataMember] 装饰了课程。

服务在 IIS 中发布,在 Windows 中发布,而不是在集成中发布。

这是 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>

编辑:

我忘记了错误,进入客户端 Microsoft 测试应用:

Échec de l'appel du 服务。可能的原因:le service est peut être hors ligne ou inaccessible ; la configuration côté client ne 对应 pas au 代理; le proxy exists n'est pas valide。 Reportez-vous à la trace de la pour pour plus de 详细信息。 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。

意思是:

服务调用失败。服务可能无法访问,现有代理无效。您可以尝试通过恢复默认配置或更新服务来创建新代理。

这是堆栈跟踪:

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 serverur (peut-être à cause de l'arrêt du service)。 Pour plus d'informations,consultez les journaux du serverur。

意思是:

http://localhost/market8/Service.svc 调用的 http 应答接收出错,端点可能未使用 HTTP 协议,或者服务器可能忽略 HTTP 请求上下文(原因:服务停止?)。

服务器堆栈跟踪:à System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest 请求, HttpAbortReason abortReason)
一个 System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan 超时)à System.ServiceModel.Channels.RequestChannel.Request(消息消息, TimeSpan 超时)à System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息 消息,TimeSpan 超时)à System.ServiceModel.Channels.ServiceChannel.Call(字符串动作, Boolean oneway, ProxyOperationRuntime 操作, Object[] ins, Object[] 出局,TimeSpan 超时)à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall、ProxyOperationRuntime 操作)à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 留言)

在 [0] 处重新抛出异常:à System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) à System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(消息数据& msgData, Int32 类型) à IService.getSupermarche() à ServiceClient.getSupermarche()

内部例外:La connexion sous-jacente a été fermée : Une erreur 不注意 s'est produite lors de la réception。一个 (这意味着:底层连接已关闭:接收时发生意外错误)

System.Net.HttpWebRequest.GetResponse() à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan 超时)

内在例外:Impossible de lire les données de la connexion de 交通 : Une connexion existsante a dû être fermée par l'hôte 遥远。
(这意味着:无法读取传输连接的数据:现有 必须关闭连接)

à System.Net.Sockets.NetworkStream.Read(Byte[] 缓冲区, Int32 偏移量,Int32 大小)→ System.Net.PooledStream.Read(Byte[] 缓冲区,Int32 偏移量,Int32 大小)à System.Net.Connection.SyncRead(HttpWebRequest 请求,布尔值 userRetrievedStream, Boolean probeRead)

内部例外: Une connexion existsante a dû être fermée par l'hôte 遥远的
(这意味着:远程主机必须关闭远程连接) à System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 偏移量,Int32 大小,SocketFlags socketFlags)à System.Net.Sockets.NetworkStream.Read(Byte[] 缓冲区,Int32 偏移量, int32 大小)

服务已部署到 IIS。

编辑 下面是控制台项目中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();

           }
        }

我使用“sqlserver”作为连接字符串,所以我也将服务连接字符串更改为“sqlserver”,但没有帮助。

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

Linq 问题? 以下是控制台项目中的引用: 以下是服务项目的参考资料:

我没有注意到有问题的想法。

【问题讨论】:

  • 那么当它尝试连接时,你会得到什么错误?你能在 SQL Server 的日志中看到连接尝试吗?如果是这样,他们说了什么错误?
  • 不幸的是错误不是英文的; Stack Overflow 是一个英语社区(我看到你已经翻译了其中的一部分,但没有翻译其余部分)。
  • 您说您的工作应用程序“或多或少”具有相同的代码,但我们无法评估,因为您没有展示它。此外,工作应用程序是否连接到同一个数据库?另外,你试过什么?启用 WCF 跟踪以查看实际异常。很有可能,因为您将 Entity Framework 实体用作 DTO(您不应该),所以您有一个循环引用,因此您的实体无法正确序列化,或者由于延迟加载,您得到了一个“上下文处理”例外。此问题中没有足够的信息来解决此问题;自己研究一下。
  • 由于there was an error at the http answer reception for the http://localhost/market8/Service.svc call,您似乎没有正确配置服务,请检查服务配置和网址。这里is the documentation。您可以使用网络浏览器查看网络服务 URL。
  • 我翻译了剩余的法语文本,并在我对问题的编辑中建议错误可能来自数据库访问。

标签: c# sql-server web-services wcf


【解决方案1】:

解决了!

事实上,借助可视化调试器和服务的本地运行(使用 WCFTestClient.exe 应用程序),我看到了对上下文的调用,即

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

            return sm;
        }

产生一个 sm 类型的变量:System.Data.DynamicProxies.Supermarche_xxx,我猜它会使服务崩溃。 然后我搜了一下,找到了:Why is EF returning a proxy class instead of the actual entity?,然后加了

ctx2.Configuration.ProxyCreationEnabled = false;

在提取数据之前,它起作用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多