Возвращение DataTables в WCF / .NET - PullRequest
       30

Возвращение DataTables в WCF / .NET

47 голосов
/ 16 августа 2008

У меня есть служба WCF, из которой я хочу вернуть DataTable. Я знаю, что это часто обсуждаемая тема, поскольку хорошая практика - возвращать ли DataTables. Давайте отложим это на мгновение.

Когда я создаю DataTable с нуля, как показано ниже, никаких проблем не возникает. Таблица создана, заполнена и возвращена клиенту, и все хорошо:

[DataContract]
public DataTable GetTbl()
{
    DataTable tbl = new DataTable("testTbl");
    for(int i=0;i<100;i++)
    {
        tbl.Columns.Add(i);
        tbl.Rows.Add(new string[]{"testValue"});
    }
    return tbl;
}

Однако, как только я выхожу из базы данных и создаю таблицу, как показано ниже, я получаю сообщение CommunicationException «Базовое соединение было закрыто: соединение было неожиданно закрыто».

[DataContract]
public DataTable GetTbl()
{
    DataTable tbl = new DataTable("testTbl");
    //Populate table with SQL query

    return tbl;
}

Таблица заполняется правильно на стороне сервера. Он значительно меньше тестовой таблицы, которую я перебрал и возвратил, а запрос небольшой и быстрый - здесь нет проблем с таймаутами или большой передачей данных. Точно такие же функции и DataContracts / ServiceContracts / BehaviorContracts используются.

Почему способ, которым таблица заполняется, имеет какое-либо отношение к таблице, возвращающейся успешно?

Ответы [ 8 ]

80 голосов
/ 03 сентября 2008

Для тех, у кого есть подобные проблемы, я решил свою проблему. Это было в несколько раз.

  • Как предположил Даррен и Пол сделал резервную копию, свойства Max..Size в конфигурации необходимо было увеличить. Утилита SvcTraceViewer помогла определить это, но она по-прежнему не всегда дает наиболее полезные сообщения об ошибках.
  • Представляется также, что при обновлении ссылки на службу на стороне клиента конфигурация иногда не обновляется должным образом (например, изменение значений конфигурации на сервере не всегда будет правильно обновляться на клиенте. Max..Size свойства несколько раз на стороне клиента и сервера в ходе моей отладки)
  • Чтобы DataTable был сериализуемым, ему нужно дать имя. Конструктор по умолчанию не дает таблице имя, поэтому:

    return new DataTable();
    

    не будет сериализуемым, в то время как:

    return new DataTable("someName");
    

    будет называть таблицу тем, что передано в качестве параметра.

    Обратите внимание, что таблице можно присвоить имя в любое время, присвоив строку свойству TableName объекта DataTable.

    var table = new DataTable();
    table.TableName = "someName";
    

Надеюсь, это кому-нибудь поможет.

14 голосов
/ 23 августа 2008

Лучший способ диагностировать ошибки WCF такого типа (те, которые действительно мало о чем говорят) - это включить трассировку. В файле web.config добавьте следующее:

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" 
              switchValue="Information" 
              propagateActivity="true">
        <listeners>
          <add name="ServiceModelTraceListener" 
               type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
               initializeData="wcf-traces.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Затем можно открыть полученный файл с помощью утилиты SvcTraceViewer.exe, которая поставляется в составе .NET Framework SDK (или вместе с Visual Studio). На моем компьютере его можно найти по адресу% PROGRAMFILES% \ Microsoft SDKs \ Windows \ v6.0A \ Bin \ SvcTraceViewer.exe.

Просто найдите сообщение об ошибке (выделено жирным красным цветом), и оно конкретно скажет вам, в чем заключается ваша проблема.

5 голосов
/ 24 октября 2011

Я добавил Datable к набору данных и возвратил таблицу примерно так ...

DataTable result = new DataTable("result");

//linq to populate the table

Dataset ds = new DataSet();
ds.Tables.Add(result);
return ds.Tables[0];

Надеюсь, это поможет :)

5 голосов
/ 21 декабря 2010

Кроме установки максимальных значений для всех атрибутов привязки.

Убедитесь, что каждая таблица, которую вы передаете / возвращаете из веб-сервиса, должна иметь имя таблицы, то есть свойство table.tablename не должно быть пустым.

3 голосов
/ 16 августа 2008

Требуемый атрибут: OperationContract (в интерфейсе) / Operation Behavior (в методе):

[ServiceContract]
public interface ITableProvider
{
    [OperationContract]
    DataTable GetTbl();
}


[OperationBehavior]
public DataTable GetTbl(){
    DataTable tbl = new DataTable("testTbl");
    //Populate table with SQL query

    return tbl;
}

Кроме того, в ... Я думаю, что конфигурация службы ... вы хотите указать, что ошибки могут быть отправлены. Возможно, вы сталкиваетесь с ошибкой, например, размером сообщения слишком велико и т. Д. Это можно исправить, обманув квоты читателя и т. Д.

По умолчанию wsHttpBinding имеет квоту размера приема, равную примерно 65 КБ, поэтому, если XML-код таблицы сериализованных данных больше этого, он выдаст ошибку (и я на 95% уверен, что таблица данных превышает 65 КБ данные в нем).

Вы можете изменить настройки для квот ридеров и т. Д. В web.config / app.config или установить их в экземпляре привязки в коде. Но да, возможно, это и есть ваша проблема, если вы не изменили ее по умолчанию.

Члены WSHttpBindingBase - просмотр свойства ReaderQuotas, а также свойства MaxReceivedMessageSize.

2 голосов
/ 24 октября 2008

Возможно, вы нарушили свою квоту - размер данных превышает максимально допустимый размер пакета для вашего соединения.

Возможно, вам нужно установить MaxReceivedMessageSize и MaxBufferSize на более высокие значения вашего соединения.

1 голос
/ 02 декабря 2016

Существует 3 причины сбоя типа возврата как datatable в службах WCF

  • Вы должны указать имя таблицы данных, например:

    MyTable=new DataTable("tableName");
    
  • Когда вы добавляете ссылку на стороне клиента службы WCF, выберите повторно используемую dll system.data

  • Укажите атрибут для datatable переменной-члена, например

    [DataMember]
    public DataTable MyTable{ get; set; }
    
0 голосов
/ 02 сентября 2008

Я думаю, что Даррен, скорее всего, прав - значения по умолчанию, предоставленные для WCF, смехотворно малы, и если вы натолкнетесь на них, вы получите ошибки, которые могут быть трудно отследить. Кажется, они появляются, как только вы пытаетесь сделать что-то, кроме простого контрольного примера. Я потратил больше времени, чем хотел бы признать проблемы с отладкой, которые оказались связаны с различными настройками конфигурации (размера) как на клиенте, так и на сервере. Я думаю, что я в конечном итоге изменил почти все из них, напр. MaxBufferPoolSize, MaxBufferSize, MaxConnections, MaxReceivedMessageSize и т. Д.

Сказав это, утилита SvcTraceViewer также упомянула великолепно. Я сталкивался с несколькими случаями, когда это было не так полезно, как хотелось бы, но в целом это хороший инструмент для анализа потока сообщений и ошибок.

...