3

EntityFrameworkとWCFを使用して簡単なテストソリューションを作成しました。サービスコントラクトにはGetAllCustomers()、データベースから顧客を取得してクライアントに返すという関数が1つだけあります。クライアントアプリは関数を呼び出し、顧客名をコンソールに書き込みます。

GetAllCustomers()クライアントからプロキシ経由で電話をかけるCommunicationExceptionと、次のメッセージが表示されます。

へのHTTP応答の受信中にエラーが発生しましたhttp://localhost:8000/Service1。これは、HTTPプロトコルを使用していないサービスエンドポイントバインディングが原因である可能性があります。これは、サーバーによってHTTP要求コンテキストが中止されたことが原因である可能性もあります(おそらくサービスのシャットダウンが原因です)。詳細については、サーバーログを参照してください。

内部の例外はSystem.Net.WebException次のとおりです。

基になる接続が閉じられました:受信時に予期しないエラーが発生しました。

次のレベルの内部例外は次のSystem.IO.IOExceptionとおりです。

トランスポート接続からデータを読み取れません:既存の接続がリモートホストによって強制的に閉じられました。

そして最後の内部例外はSystem.Net.Sockets.SocketException

既存の接続がリモートホストによって強制的に閉じられました

クライアントコードは次のとおりです。

static void Main(string[] args)
{
    Console.WriteLine("Press Enter to begin.");
    Console.ReadLine();

    ServiceReference1.Service1Client MyService = new ServiceReference1.Service1Client();

    CUSTOMER[] cl = MyService.GetAllCustomers();

    foreach (CUSTOMER c in cl)
    {
        Console.WriteLine(c.CUSTFNAME + " " + c.CUSTLNAME);
    }

    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
}

ホストアプリケーションのコードは次のとおりです。

static void Main(string[] args)
{
    ServiceHost hostA = null;

    try
    {
        hostA = new ServiceHost(typeof(Service1), new Uri("http://localhost:8000") );
        hostA.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "Service1");

        hostA.Open();

        Console.WriteLine();
        Console.WriteLine("Host started.  Press Enter to terminate host.");
        Console.ReadLine();

    }
    finally
    {
        if (hostA.State == CommunicationState.Faulted)
            hostA.Abort();
        else
            hostA.Close();
    }
}

関数のサービスライブラリコードは次のとおりです。

public HashSet<CUSTOMER> GetAllCustomers()
{
    var db = new TRS11Entities();

    HashSet<CUSTOMER> TheCusts = new HashSet<CUSTOMER>();

    foreach (CUSTOMER c in db.CUSTOMERs)
    {
        TheCusts.Add(c);
    }

    //CUSTOMER TestCust1 = new CUSTOMER();
    //TestCust1.CUSTFNAME = "Joe";
    //TestCust1.CUSTLNAME = "Schmoe";
    //CUSTOMER TestCust2 = new CUSTOMER();
    //TestCust2.CUSTFNAME = "Peter";
    //TestCust2.CUSTLNAME = "Pumpkineater";
    //TheCusts.Add(TestCust1);
    //System.Threading.Thread.Sleep(45000);
    //TheCusts.Add(TestCust2);

    return TheCusts;
}

不思議なことに、foreachブロックをその下のコメントアウトされたコードに置き換えてデータベースをバイパスすると、うまく機能します。

私は最初、データベースクエリに時間がかかりすぎるというタイムアウトの問題である可能性があると考えました。ただし、私のテストコードには45秒間のスリープがあり、それでもデータはクライアントに正常に返されます。元のコードでは、わずか約3秒後に例外が発生します。

また、エンドポイント/プロキシ経由ではなく、WCFサービスを直接インスタンス化して元の関数(foreachブロックを使用)を呼び出すと、正常に実行され、データベース内のすべての顧客が返されます。

最後に、返されたデータセットが大きすぎることが問題である可能性があると考えたため、foreachブロックを変更し、最初の5人の顧客を結果に追加した後にbreakステートメントを挿入しましたが、それでも例外が発生しました。

それで、他に何がこれを引き起こしている可能性がありますか?

4

3 に答える 3

2

何が問題なのか見分けるのは難しいです。WCFトレースと診断をオンにして、詳細を確認することができます。

すばやく作業を開始するには-Web(またはアプリ)構成で:

1)構成要素の下の任意の場所にSystem.Diagnosticsセクションを追加します。パスは、ファイルを保存するパスに置き換えることができます。

<system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelMessageLoggingListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
      <source name="System.ServiceModel" switchValue="Warning, ActivityTracing" propagateActivity="true">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelTraceListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="C:\temp\services_messages.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelMessageLoggingListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
        <filter type="" />
      </add>
      <add initializeData="C:\temp\services_tracelog.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
        <filter type="" />
      </add>
    </sharedListeners>
  </system.diagnostics>

2)system.ServiceModelの下に、次を追加します。

<diagnostics wmiProviderEnabled="false">
      <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
    </diagnostics>

3)C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v7.0A \ Bin \で、SvcTraceViewer.exeを起動します。メッセージトレース(services_messages.svclog)とサービストレースログ(services_tracelog.svclog)の両方をロードします。ツールにドロップファイルをドラッグするか、ファイルを開いてから別のファイルを追加することができます

4)問題のある赤い太字を探します。

WCF構成の編集をより快適にしたい場合は、SvcTraceViewer.exe(#3)と同じフォルダーにあるSvcConfigEditor.exeを使用できます。構成ファイルを開くだけで、診断を開始/停止および構成できるDiagnosticsフォルダーが表示されます。

于 2012-12-31T04:10:42.123 に答える
1

問題は、Entity FrameworkのCUSTOMERタイプに詳細レコード(販売など)のセット(コンテナータイプ)が含まれていて、データが大きくなりすぎていたことだと思います。私はそれらを持たない新しいタイプを作成することになり、その後はうまくいきました。

于 2013-01-02T23:30:52.733 に答える
0

DataContext.ContextOptions.ProxyCreationEnabled=trueがfalseに変更された場合

DataContext.ContextOptions.ProxyCreationEnabled = true

また

複製された顧客を返す

public class Customer:ICloneable {Public int Id {get; セットする; }

public object Clone()
 {
     var cloneObject = new Customer();
      cloneObject.Id=this.Id; 
      return cloneObject;
 }

}

public HashSet GetAllCustomers(){var db = new TRS11Entities(); HashSet TheCusts = new HashSet(); foreach(db.CUSTOMERsのCUSTOMER c){TheCusts.Add(c.Clone()); }

//CUSTOMER TestCust1 = new CUSTOMER();
//TestCust1.CUSTFNAME = "Joe";
//TestCust1.CUSTLNAME = "Schmoe";
//CUSTOMER TestCust2 = new CUSTOMER();
//TestCust2.CUSTFNAME = "Peter";
//TestCust2.CUSTLNAME = "Pumpkineater";
//TheCusts.Add(TestCust1);
//System.Threading.Thread.Sleep(45000);
//TheCusts.Add(TestCust2);

return TheCusts;

}

于 2012-12-31T04:40:06.450 に答える