2008-08-15 4 views
44

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

Когда я создаю 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.

Зачем нужно, чтобы стол, который был заполнен, имел какое-либо оповещение о возврате стола?

ответ

75

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

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

    return new DataTable(); 
    

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

    return new DataTable("someName"); 
    

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

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

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

Надеется, что кому-то поможет.

+1

Очень странно с именем thingy. У меня была такая же проблема. Установка имени в DataTable решила его ... Странно. – MartinHN 2009-08-01 17:52:30

+1

+1 потому что установка имени таблицы также исправила его для меня. – 2010-02-19 22:19:45

3

Атрибут вы хотите OperationContract (на интерфейсе)/Операция Поведение (по методу):

[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   KB, поэтому, если XML-таблица с сериализованной таблицей данных больше, это приведет к ошибке (и я уверен, что 95% таблица данных больше 65   KB с данными в нем).

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

WSHttpBindingBase Members - Посмотрите на свойство ReaderQuotas, а также свойство MaxReceivedMessageSize.

14

Лучший способ диагностики этих ошибок 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 SDK \ Windows \ v6.0A \ Bin \ SvcTraceViewer.exe.

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

+0

Вы можете найти файл журнала `ФОС-traces.svclog` в` Debug` папке ваш проект. – 2017-12-20 19:04:22

0

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

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

2

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

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

5

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

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

5

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

DataTable result = new DataTable("result"); 

//linq to populate the table 

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

Надеется, что это помогает :)

1

Есть 3 причины неудачного возвращаемого типа как datatable в WCF услугах

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

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

  • Укажите атрибут на datatable переменную-член как

    [DataMember] 
    public DataTable MyTable{ get; set; } 
    
Смежные вопросы