1

VS 2012で非常に基本的なWCFサービス(WCF 4.0)を開発しました。SQLServer2012でAdventureWorks2012データベースをホストし、.Net4.0フレームワークがインストールされたIIS7を使用しています。

VS 2012を使用してローカル開発IISでサービスを実行すると、すべてが正常に機能します(.svcをホストするWebサイトのweb.configの接続文字列が統合セキュリティを使用するように設定されているためです-接続文字列は以下のとおりです)

<add name="AdventureWorksEntities" connectionString="metadata=res://*/ProductsModel.csdl|res://*/ProductsModel.ssdl|res://*/ProductsModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=adams_pc;initial catalog=AdventureWorks2012;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient"/>

WebサイトをローカルIISに公開し、ASP.NET 4.0アプリケーションプールで実行すると、実際にはデータベースに接続されていないようです(コンソールテストクライアントを実行している場合、エンティティモデルのオブジェクトにはデータがありません)それらの中で)。

私はAdventureWorks2012データベースにIISAPPPOOL\ ASP.NET v4.0という名前のユーザーを設定し、データベースへのdbo.ownerアクセス​​を許可しましたが、それでも接続を確立できません。

私は何が欠けていますか?ホスティングウェブサイトの接続文字列を変更する必要がありますか?

詳しくは:

ローカルで実行すると(開発サーバーとは、アプリケーションのデバッグ時に実行されるIISのローカルインスタンスを意味します)、情報がデータベースから取得され、テストコンソールアプリケーションに表示されます。

サービスを展開し、ホストされたWCFサービスを使用するようにテストコンソールアプリケーションで参照を変更すると、データがまったく取得されません。スローされる例外は、テストコードのnull参照例外ですが、これは、サービスが使用するエンティティモデルにデータが入力されていないためです。データベース接続に関して例外は表示されませんが、サービスからクライアントに例外を渡す方法を学習するまでには至っていません。この簡単なテストは、私が作業している本と同じように機能することを期待していました。

また、データベース接続を確立する際のエラーを正確に把握するために、他に何かすべきことはありますか?

サービス:

Imports System.Text
Imports System.Linq
Imports System
Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.Runtime.Serialization
Imports ProductsEntityModel
'NOTE: You can use the "Rename" command on the context menu to change the class name "Service" in code, svc and config file together.

'WCF service that implements the service contract
'This implementation performs minimal error checking and exception handling
Public Class ProductsServiceImpl
Implements IProductsService

Public Function ChangeStockLevel(productNumber As String, newStockLevel As Short, shelf As String, bin As Short) As Boolean Implements IProductsService.ChangeStockLevel
    'Modify the current stock level of the selected product in the ProductInventory table.
    'If the update is successful then return True, otherwise return False.

    'The Product and ProductIventory tables are joined over the ProductID column.

    Try
        'Connect to the AdventureWorks database using the Entity Framework
        Using database As New AdventureWorksEntities()
            ' Find the ProductID for the specified product
            Dim qryProductID = (From p In database.Products
                             Where String.Compare(p.ProductNumber, productNumber) = 0
                             Select p.ProductID).First
            'Find the ProductInventory object that matches the paramters passed into the operation
            Dim productInv As ProductInventory = database.ProductInventories.First(Function(pi) String.Compare(pi.Shelf, shelf) = 0 And pi.Bin = bin And pi.ProductID = qryProductID)

            'Update the stock level for the ProductInventory object
            productInv.Quantity += newStockLevel

            'Save the change back to the database
            database.SaveChanges()
        End Using
    Catch ex As Exception
        Return False
    End Try
    Return True
End Function


Public Function CurrentStockLevel(ByVal productNumber As String) As Integer Implements IProductsService.CurrentStockLevel
    'Obtain the total stock level for the specified product
    'The stock level is calculated by summing the quantity of the product available in all the bins in 
    'the ProductInventory table

    'The Product and ProductInventory tables are joined over the ProductID column.
    Dim stockLevel As Integer = 0

    Try
        'Connect to the AdventureWorks database by using the Entity Framework.
        Using database As New AdventureWorksEntities()
            stockLevel = (From pi In database.ProductInventories
                          Join p In database.Products
                          On pi.ProductID Equals p.ProductID
                          Where String.Compare(p.ProductNumber, productNumber) = 0
                          Select CInt(pi.Quantity)).Sum

        End Using
    Catch ex As Exception

    End Try
    Return stockLevel
End Function

Public Function GetProduct(productNumber As String) As ProductData Implements IProductsService.GetProduct
    'Create a reference to a ProductData object
    Dim productData As ProductData = Nothing

    Try
        'Connect to the AdventureWorks database by using Entity Framework
        Using database As New AdventureWorksEntities()
            Dim matchingProduct As Product = database.Products.First(Function(p) String.Compare(p.ProductNumber, productNumber) = 0)
            productData = New ProductData With {.Name = matchingProduct.Name, .ProductNumber = matchingProduct.ProductNumber, .Color = matchingProduct.Color, .ListPrice = matchingProduct.ListPrice}
        End Using
    Catch ex As Exception

    End Try
    Return productData
End Function

Public Function ListProducts() As List(Of String) Implements IProductsService.ListProducts
    'Create a list for holding product numbers
    Dim productsList As New List(Of String)

    Try
        'Connect to the AdventureWorks database by uysing the Entity Framework
        Using database As New AdventureWorksEntities()
            ' Fetch the product number of every product in the database
            Dim products = From Product In database.Products
                           Select Product.ProductNumber

            productsList = products.ToList
        End Using
    Catch ex As Exception

    End Try
    'Return the list of product numbers
    Return productsList
End Function
End Class

インターフェース:

Imports System.Text
Imports System.Linq
Imports System
Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.Runtime.Serialization
'NOTE: You can use the "Rename" command on the context menu to change the interface name "IService" in both code and config file together.
'The Data Contact describes the details of a Product object passed to client applications (this is a return object).
<DataContract>
Public Class ProductData
<DataMember>
Public Name As String

<DataMember>
Public ProductNumber As String

<DataMember>
Public Color As String

<DataMember>
Public ListPrice As Decimal
End Class
'The Service Contact describes the operations that the WCF service provides (these are the methods available to call)
<ServiceContract>
Public Interface IProductsService

'Get the product number of every product
<OperationContract>
Function ListProducts() As List(Of String)

'Get the details of a single product
<OperationContract>
Function GetProduct(ByVal productNumber As String) As ProductData

'Get the current stock level for a product
<OperationContract>
Function CurrentStockLevel(ByVal productNumber As String) As Integer

'Change the stock level for a product
<OperationContract>
Function ChangeStockLevel(ByVal productNumber As String, ByVal newStockLevel As Short, ByVal shelf As String, ByVal bin As Int16) As Boolean

End Interface

クライアント:

Imports System.ServiceModel
Imports ProductsClient.ProductsService

Module Module1

Sub Main()
    ' Create a proxy object and connect to the service
    Dim proxy As New ProductsServiceClient()

    ' Test the operations of the service

    ' Obtain a list of all the products
    Console.WriteLine("Test 1: List all products")
    Dim productNumbers As String() = proxy.ListProducts
    For Each productNumber As String In productNumbers
        Console.WriteLine("Number: {0}", productNumber)
    Next
    Console.WriteLine()

    Console.WriteLine("Test 2: Display the Details of a product")
    Dim product As ProductData = proxy.GetProduct("WB-H098")
    Console.WriteLine("Number: {0}", product.ProductNumber)
    Console.WriteLine("Name: {0}", product.Name)
    Console.WriteLine("Color: {0}", product.Color)
    Console.WriteLine("Price: {0}", product.ListPrice)
    Console.WriteLine()

    ' Query the stock level of this product
    Console.WriteLine("Test 3: Display the stock level of a product")
    Dim numInStock As Integer = proxy.CurrentStockLevel("WB-H098")
    Console.WriteLine("Number in stock: {0}", numInStock)
    Console.WriteLine()

    ' Modify the stock level of this product
    Console.WriteLine("Test 4: Modify the stock level of a product")
    If proxy.ChangeStockLevel("WB-H098", 100, "N/A", 0) Then
        numInStock = proxy.CurrentStockLevel("WB-H098")
        Console.WriteLine("Stock level changed. Current stock level: {0}", numInStock)
    Else
        Console.WriteLine("Stock level update failed.")
    End If
    Console.WriteLine()

    ' Disconnect from the service
    proxy.Close()
    Console.WriteLine("Press ENTER to finish")
    Console.ReadLine()
End Sub

End Module

そして、ちょっとした笑いのために、これは私がAdventureWorks2012データベースでユーザーを設定するために使用したSQLスクリプトです。

USE [AdventureWorks2012]
GO
CREATE USER [IIS APPPOOL\DefaultAppPool] FOR LOGIN [IIS APPPOOL\DefaultAppPool]
GO
EXEC sp_addrolemember N'db_owner', [IIS APPPOOL\DefaultAppPool]
GO
GO
CREATE USER [IIS APPPOOL\ASP.NET v4.0] FOR LOGIN [IIS APPPOOL\ASP.NET v4.0]
GO
EXEC sp_addrolemember N'db_owner', [IIS APPPOOL\ASP.NET v4.0]
GO

そして、これがクライアントのapp.configのserviceModel部分であるため、エンドポイントを確認できます

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IProductsService" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost/ProductsService/Service.svc" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IProductsService" contract="ProductsService.IProductsService"
            name="BasicHttpBinding_IProductsService" />
    </client>
</system.serviceModel>
4

2 に答える 2

2

サービスコードはすべての例外をサイレントにキャッチします。そのようなコードは受け入れられません:)。

実際の例外をデバッグするには、管理者としてVisualStudioを実行します。[デバッグ]->[プロセスに接続]->[すべてのユーザーのプロセスを表示する]をオンにします->[w3wp.exe]を選択します。テストアプリを実行し、VisualStudioでWebサービスの例外が発生するのを待ちます。

于 2012-06-10T19:42:24.563 に答える
0

問題は、アプリプールのサーバーユーザーが見つからなかったことです。私が投稿したSQLスクリプトは、アプリプールIDのデータベースユーザーを作成しただけでしたが、同じIDのサーバーログインはありませんでした。そのユーザーを追加すると(そして、IIS APPPOOL \ ASP.NET v4.0を手動で入力し、Windowsログイン選択でオブジェクトとして選択しようとしないでください)、すべて正常に機能しました。

結局はまったく些細なことでしたが、Grzegorzの助けに感謝します!

于 2012-06-10T22:28:32.793 に答える