powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WCF, Web Services, Remoting [игнор отключен] [закрыт для гостей] / WCF. Эффективнее передать DataSet
45 сообщений из 45, показаны все 2 страниц
WCF. Эффективнее передать DataSet
    #36895775
Hug
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hug
Гость
Добрый день, коллеги.
Столкнулся с необходимостью передавать эффективно данные с сервиса на клиент.
Сейчас передает сериализованный в xml datatable.
Естественно большой overhead.
Необходимо как-то плавно переплыть к бинарной кодировке сообщений и эффективному контейнеру передачи (List<T>).
DTO нет. Есть тока xml дататейблов. Можно ли как - то конвертить тейблы к спискам,
или клиент не сможет все это дело десериализовать? А может linq в помощь?

Вообщем, не обладаю большим опытом в этом, прошу совета как бы эффективнее бы послать тейбл через wcf.

PS На клиенте все операции опять идут с DataTable.
PSS: Http,Tcp биндинги
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36896434
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hug,

давай выложи объем оверхеда в килобайтах, и прикинем, есть ли ,что с меньшим оверхедом.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36896465
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hug
Таскать таблицы - не кошерно. Безусловно надо переходить к коллекциям. DTO можно и написать.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36898335
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Переходить на коллекции надо естественно и сервером и клиентом одновременно.
Нельзя передать коллекции, а принять таблицы ;)

По поводу бинарной кодировки - тоже верное направление.

Вот некоторый промежуточный вариант - использование массива object, вместо datatable. Велосипед конечно.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36900838
Hug
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hug
Гость
Переходить не имею возможности (Куча legacy кода с DataTable)

Объем оверхеда = разница между xml с кучой полей и binary.

Покурю Ваш велосипед. На запас оставлю gzip=>byte[]=>mtom


Всем спасибо большое за участие. Отпостюсь о результатах.

Считаю тема очень актуальная.
Многие скоро начнут свое старое asmx(времен 1.0, без генериков, с датасетами) переводить на wcf.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36900864
Фотография Шайтан
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HugМногие скоро начнут свое старое asmx(времен 1.0, без генериков, с датасетами) переводить на wcf.

уже начали... точнее - ПОНАЧИНАЛИ и забили : )
ибо, озадачились простым вопросом - а оно зачем надо (менять)?
уже 5 лет работает и, если не трогать , ещё не один раз по 5 лет проработает

мудрые говорят: лучшее - враг хорошего
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36900930
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шайтан, +1

P.S. Зачем ломать то, что прекрасно работает. Новые проекты, да - на WCF, тут всё правильно.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36911635
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тут посмотри
я использую

тесты RsdnDetaSerializer
Serialization: 150 ms Loading: 450 Length: 1 053 824 bytes
Serialization: 140 ms Loading: 451 Length: 1 053 824 bytes
Serialization: 140 ms Loading: 451 Length: 1 053 824 bytes

BinaryFormatter
Serialization: 2 123 ms Loading: 7 631 Length: 6 985 259 bytes
Serialization: 1 773 ms Loading: 7 701 Length: 6 985 259 bytes
Serialization: 1 773 ms Loading: 7 701 Length: 6 985 259 bytes

XmlSerializer
Serialization: 1 793 ms Loading: 7 591 Length: 9 309 050 bytes
Serialization: 1 652 ms Loading: 7 561 Length: 9 309 050 bytes
Serialization: 1 662 ms Loading: 7 561 Length: 9 309 050 bytes

SoapFormatter
Serialization: 2 594 ms Loading: 9 233 Length: 11 001 874 bytes
Serialization: 2 573 ms Loading: 9 173 Length: 11 001 874 bytes
Serialization: 2 554 ms Loading: 9 163 Length: 11 001 874 bytes
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36911714
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas,

что еще хотелось бы узнать,это какой процессор и сколько памяти использовали для теста.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36911792
ВМоисеев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hug, 12 окт 10, 20:21 [9596316]

Посмотри здесь , в конце статьи приведены и цифры и вывод.

С уважением, Владимир.
p.s. DateSet сериализуем.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36911832
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiKbarrabas,

что еще хотелось бы узнать,это какой процессор и сколько памяти использовали для теста.
эти тесты автора, свои я не помню (сейчас дома, а не на работе), там же есть исходник просто запусти в новом проекте, на своей машине.
у себя еще gzip использую
причем судя по форуму уже 2я версия, а я давно уже юзаю (подпиливал под себя) возможно и первую версию, по сути можно выкинуть версии строк, мне они не нужны
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36911844
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasAlexeiKbarrabas,

что еще хотелось бы узнать,это какой процессор и сколько памяти использовали для теста.
эти тесты автора, свои я не помню (сейчас дома, а не на работе), там же есть исходник просто запусти в новом проекте, на своей машине.
у себя еще gzip использую
причем судя по форуму уже 2я версия, а я давно уже юзаю (подпиливал под себя) возможно и первую версию, по сути можно выкинуть версии строк, мне они не нужны
хотя нет, там 2003год, значит эта версия, я не так давно этим озадачился
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36923156
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas тут посмотри
я использую


Хм. Это для того чтобы потом подсунуть сериализованные данные в виде DataTable - например в ObjectDataSource - надо еще свою обертку написать, которая будет десериализовать?
Или можно как-то по другому извернуться?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36923344
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabas тут посмотри
я использую


Хм. Это для того чтобы потом подсунуть сериализованные данные в виде DataTable - например в ObjectDataSource - надо еще свою обертку написать, которая будет десериализовать?
Или можно как-то по другому извернуться?
так там сериализатор и десиализатор
сериализуешь в byte[], зипуешь если нужно, передаешь кленту, а на клиенте десериализуешь в DS или DataTable зачем обертку?
это класс для компактной записи инфы из датасета, как я понял тупо без всяких лишних тегов пишет в определённо порядке инфу через разделитель, и читает обратно в датасет
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36923466
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas
так там сериализатор и десиализатор
сериализуешь в byte[], зипуешь если нужно, передаешь кленту, а на клиенте десериализуешь в DS или DataTable зачем обертку?
это класс для компактной записи инфы из датасета, как я понял тупо без всяких лишних тегов пишет в определённо порядке инфу через разделитель, и читает обратно в датасет

Это я все вижу. Просто получается, метод WCF сервиса, будет возвращать не DataTabel или DataSet, а сериализованный контент.
А такой метод нельзя указазать для ObjectDataSource. Надо будет писать врапер, который будет дергать функции WCF сервиса, и полученное десериализовать в DataTable.


Сейчас у меня декларативно указано

Код: plaintext
1.
2.
3.
4.
	<asp:ObjectDataSource ID="odsOrders" runat="server" SelectMethod="GetOrdersMmts" TypeName="LcrServiceReference.LcrWebService"
		EnableCaching="true" CacheDuration="300"
		onobjectcreating="OdsCreating"></asp:ObjectDataSource>


Где GetOrdersMmts - это метод WCF сервиса (LcrServiceReference.LcrWebService), возвращает DataTable.
Если он начнет возвращать сериализованный вручную контейнер - без доп обертки не обойтись.

Не?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36923779
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну да, конечно нужно будет создать метод в котором вызовет метод сервиса и результат десериализует в таблицу.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36923800
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чего то я не понял, как GetOrdersMmts у вас возвращает DataTable?
Почему у меня не получилось создать OperationContract возвращающий произвольную таблицу.

у вас там прям

[OperationContract]
DataTable GetOrdersMmts();
??
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924169
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasчего то я не понял, как GetOrdersMmts у вас возвращает DataTable?
Почему у меня не получилось создать OperationContract возвращающий произвольную таблицу.

у вас там прям

[OperationContract]
DataTable GetOrdersMmts();
??

ну да
Код: plaintext
1.
[OperationContract]
public DataTable GetOrdersMmts();
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924549
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabasчего то я не понял, как GetOrdersMmts у вас возвращает DataTable?
Почему у меня не получилось создать OperationContract возвращающий произвольную таблицу.

у вас там прям

[OperationContract]
DataTable GetOrdersMmts();
??

ну да
Код: plaintext
1.
[OperationContract]
public DataTable GetOrdersMmts();

а понял нужно имя давать DataTable иначе ошибка (оказывается известная фишка)
но rsdn метод эффективнее передает большие объемы, т.ч. на нем оставлю
да и я не вызываю проксю напрямую, у меня класс обертка для нее есть, т.к. в проксе только один метод в которую передаю имя действия параметры для него, а уж параметры и результат зависит от имени метода
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924851
ВМоисеев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>barrabas, 27.10.2010, 17:54 [9687314]
>ну да, конечно нужно будет ...

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

С уважением,
Владимир
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924905
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВМоисеев>barrabas, 27.10.2010, 17:54 [9687314]
>ну да, конечно нужно будет ...

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

С уважением,
Владимир
ну тогда и передавать можно было коллекцию объектов, просто зачастую нужно передать компиляцию из многих объектов для простого отображения (ну отчёт например, пара полей из обного объекта, пара из другого, какието вычисления по третьему), передавать объекты целиком на клиента и там их обрабатывать не всегда эффективнее, чаще лучше написать селект в БД и передать результат, как произвольный дататайбл, для отчёта
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924908
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasВМоисеев>barrabas, 27.10.2010, 17:54 [9687314]
>ну да, конечно нужно будет ...

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

С уважением,
Владимир
ну тогда и передавать можно было коллекцию объектов, просто зачастую нужно передать компиляцию из многих объектов для простого отображения (ну отчёт например, пара полей из обного объекта, пара из другого, какието вычисления по третьему), передавать объекты целиком на клиента и там их обрабатывать не всегда эффективнее, чаще лучше написать селект в БД и передать результат, как произвольный дататайбл, для отчёта
а плодить объекты типа Запись для отчёта 1 как то глупо ихмо
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36924980
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потестил я этот сериализатор. большого выигрыша если честно, я не заметил.
Но с помощью тестов, я нашел одну нехорошую у меня в сервисе вещь.
Сейчас еще разок проверю, отпишусь.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925049
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasпотестил я этот сериализатор. большого выигрыша если честно, я не заметил.
Но с помощью тестов, я нашел одну нехорошую у меня в сервисе вещь.
Сейчас еще разок проверю, отпишусь.
gzip прикрутил?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925379
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabashstasпотестил я этот сериализатор. большого выигрыша если честно, я не заметил.
Но с помощью тестов, я нашел одну нехорошую у меня в сервисе вещь.
Сейчас еще разок проверю, отпишусь.
gzip прикрутил?


Неа. Как прикручивать?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925388
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabashstasпотестил я этот сериализатор. большого выигрыша если честно, я не заметил.
Но с помощью тестов, я нашел одну нехорошую у меня в сервисе вещь.
Сейчас еще разок проверю, отпишусь.
gzip прикрутил?


Неа. Как прикручивать?
использовать GZipStream
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925407
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот что я использую
чуток подпилил под себя методы и зипование прикрутил
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
    public class DataSetSerializer
    {
        static readonly DataRowVersion[] _aryVer = new DataRowVersion[2] { DataRowVersion.Original, DataRowVersion.Current };

        // Массив для перемапливания TypeCode на Type
        // TypeCode это перечисление включающее константы для базовых типов.
        static readonly Type[] _TypeMap;

        // Статический конструктор. Нужен для инициализации _TypeMap.
        static DataSetSerializer()
        {
            // TypeCode.DBNull и TypeCode.Empty пропущены, так как они 
            // по сути, не являются типами.
            _TypeMap = new Type[(int)TypeCode.String + 1];
            _TypeMap[(int)TypeCode.Object] = typeof(Object);
            _TypeMap[(int)TypeCode.Boolean] = typeof(Boolean);
            _TypeMap[(int)TypeCode.Char] = typeof(Char);
            _TypeMap[(int)TypeCode.SByte] = typeof(SByte);
            _TypeMap[(int)TypeCode.Byte] = typeof(Byte);
            _TypeMap[(int)TypeCode.Int16] = typeof(Int16);
            _TypeMap[(int)TypeCode.UInt16] = typeof(UInt16);
            _TypeMap[(int)TypeCode.Int32] = typeof(Int32);
            _TypeMap[(int)TypeCode.UInt32] = typeof(UInt32);
            _TypeMap[(int)TypeCode.Int64] = typeof(Int64);
            _TypeMap[(int)TypeCode.UInt64] = typeof(UInt64);
            _TypeMap[(int)TypeCode.Single] = typeof(Single);
            _TypeMap[(int)TypeCode.Double] = typeof(Double);
            _TypeMap[(int)TypeCode.Decimal] = typeof(Decimal);
            _TypeMap[(int)TypeCode.DateTime] = typeof(DateTime);
            _TypeMap[(int)TypeCode.String] = typeof(String);
        }

        ///////////////////////////////////////////////////////////////////////
        // Сериализация.

        public static void SerializeDataSet(Stream stream, DataSet ds)
        {
            BinaryWriter bw = new BinaryWriter(stream);
            DataTableCollection tables = ds.Tables;

            bw.Write(ds.DataSetName);
            bw.Write(tables.Count);
            foreach (DataTable dt in tables)
            {	// Вообще-то foreach-и лучше на всякий пожарный избегать.
                // Но мне было в лом.
                SerializeDataTable(bw, dt);
            }
        }

        public static void SerializeDataTable(BinaryWriter bw, DataTable dt)
        {
            DataColumnCollection columns = dt.Columns;
            int iColCount = columns.Count;
            TypeCode[] colTypeCodes = new TypeCode[iColCount];

            bool[] aryIsNullabl = new bool[iColCount];

            // Имя таблицы
            bw.Write(dt.TableName);

            bw.Write(iColCount);
            // Получаем и записываем описание колонок.
            for (int i = 0; i < iColCount; i++)
            {
                DataColumn dc = columns[i];
                // Получаем TypeCode для типа обрабатываемой колонки.
                TypeCode tc = Type.GetTypeCode(dc.DataType);
                // Запоминаем TypeCode колонки в соотвествующем массиве.
                colTypeCodes[i] = tc;
                bw.Write(dc.ColumnName);
                // Записываем TypeCode как Int32. Можно было бы и 
                // сэкономить 3 байта. :)
                bw.Write((Int32)tc);

                // Создаем массив информации о поддержке колонками DBNull
                aryIsNullabl[i] = dc.AllowDBNull;
            }


            // Записываем битовое поле описывающее колонки поддерживающие
            // DBNull. Если бит поднят, значит, колонка поддерживает DBNull.
            BitArray bitsNull = new BitArray(aryIsNullabl);
            byte[] byteNull = new byte[(iColCount + 7) / 8];
            bitsNull.CopyTo(byteNull, 0);
            bw.Write(byteNull);

            ///////////////////////////////////////////////////////////////
            // add data

            // count rows
            bw.Write(dt.Rows.Count);

            // Записываем строки
            foreach (DataRow dr in dt.Rows)
            {
                byte verFlags = 0;
                int iVerStart;
                int iVerEnd;
                // Разбираемся, какие версии нужно писать.
                // Всего есть два варианта: Original и Current
                DataRowState state = dr.RowState;
                switch (state)
                {
                    // Original + Current и они равны!
                    case DataRowState.Unchanged:
                        iVerStart = 0;
                        iVerEnd = 0;
                        verFlags = 0;
                        break;
                    case DataRowState.Deleted: // Только Original
                        iVerStart = 0;
                        iVerEnd = 0;
                        verFlags = 1;
                        break;
                    case DataRowState.Added: // Только Current
                        iVerStart = 1;
                        iVerEnd = 1;
                        verFlags = 2;
                        break;
                    // Original + Current и они НЕ равны!
                    case DataRowState.Modified:
                        iVerStart = 0;
                        iVerEnd = 1;
                        verFlags = 3;
                        break;
                    default:
                        throw new ApplicationException(
                            "Недопустимое состояние строки: " + state.ToString());
                }

                // Пишем описание версий. Временно, так как на этом мы
                // теряем байт на строку. Куда лучше писать дополнительные два
                // бита в битовое поле DbNull (хотя это и не красиво).
                bw.Write(verFlags);

                // Записываем версии текущей строки. Всего их может быть две.
                // в принципе можно было бы для случая DataRowState.Modified
                // писать только дельту данных. Но это как-нибудь потом. :)
                for (int iVetIndex = iVerStart; iVetIndex <= iVerEnd; iVetIndex++)
                {
                    DataRowVersion drv = _aryVer[iVetIndex];

                    // Создаем и заполняем битовое поле. Если бит поднят,
                    // значит, соответствующая колонка содержит DBNull.
                    bitsNull.SetAll(false);
                    for (int i = 0; i < iColCount; i++)
                    {
                        if (dr[i, drv] == DBNull.Value)
                            bitsNull.Set(i, true);
                    }
                    bitsNull.CopyTo(byteNull, 0);
                    // Записываем битовое поле в стрим.
                    bw.Write(byteNull);

                    // Перебираем колонки и пишем данные...
                    for (int i = 0; i < iColCount; i++)
                    {
                        // Если колонка содержит DBNull, записывать ее значение 
                        // ненужно.
                        object data = dr[i, drv];
                        if (data == DBNull.Value) // Учитываем версию!
                            continue;

                        // Записываем данные ячейки.
                        switch (colTypeCodes[i])
                        {	// Каждому типу соответствует переопределенная функция...
                            case TypeCode.Boolean: bw.Write((Boolean)data); break;
                            case TypeCode.Char: bw.Write((Char)data); break;
                            case TypeCode.SByte: bw.Write((SByte)data); break;
                            case TypeCode.Byte: bw.Write((Byte)data); break;
                            case TypeCode.Int16: bw.Write((Int16)data); break;
                            case TypeCode.UInt16: bw.Write((UInt16)data); break;
                            case TypeCode.Int32: bw.Write((Int32)data); break;
                            case TypeCode.UInt32: bw.Write((UInt32)data); break;
                            case TypeCode.Int64: bw.Write((Int64)data); break;
                            case TypeCode.UInt64: bw.Write((UInt64)data); break;
                            case TypeCode.Single: bw.Write((Single)data); break;
                            case TypeCode.Double: bw.Write((Double)data); break;
                            case TypeCode.Decimal: bw.Write((Decimal)data); break;
                            case TypeCode.DateTime:
                                // Для DateTime приходится выпендриваться особым образом.
                                bw.Write(((DateTime)(data)).ToFileTime());
                                break;
                            case TypeCode.String: bw.Write((String)data); break;
                            default:
                                // На всякий случай пробуем записать неопознанный тип
                                // виде строки.
                                bw.Write(data.ToString());
                                break;
                        }
                    }
                }
            }
        }

        public static void SerializeDataTable(Stream stream, DataTable dt)
        {
            BinaryWriter bw = new BinaryWriter(stream);
            SerializeDataTable(bw, dt);
        }

        ///////////////////////////////////////////////////////////////////////
        // Десериализация

        public static DataTable DeserializeTable(BinaryReader br)
        {
            DataColumn dc;
            DataRow dr;

            // Имя DataTable тоже передается в качестве параметра конструктора.
            DataTable dt = new DataTable(br.ReadString());
            dt.BeginLoadData();

            int iColCount = br.ReadInt32();
            dt.MinimumCapacity = iColCount;

            // В этом массив будут записаны TypeCode-ы для колонок DataTable-а.
            TypeCode[] colTypeCodes = new TypeCode[iColCount];
            // А в этот массив будут записаны типы (Type) колонок DataTable-а
            // соотвествующие TypeCode-ам.
            for (int c = 0; c < iColCount; c++)
            {
                string colName = br.ReadString();
                // Считываем TypeCode.
                TypeCode tc = (TypeCode)br.ReadInt32();
                // Помещаем TypeCode в массив для дальнейшего использования.
                colTypeCodes[c] = tc;
                // Получаем (через мап) тип соответствующий TypeCode-у.
                Type type = _TypeMap[(int)tc];
                // Создаем колонку с полученным именем и типом.
                dc = new DataColumn(colName, type);
                dt.Columns.Add(dc);
            }


            // Считываем список nullabl-колонок.
            int iBitLenInBytes = (iColCount + 7) / 8;
            byte[] byteNull = new byte[iBitLenInBytes];
            br.Read(byteNull, 0, iBitLenInBytes);
            BitArray bitsNull = new BitArray(byteNull);
            bitsNull.Length = iColCount;
            bool[] aryIsNullabl = new bool[iColCount];
            bitsNull.CopyTo(aryIsNullabl, 0);

            object[] ad = new object[iColCount];


            int counRows = br.ReadInt32();
            DataRowCollection rows = dt.Rows;
            for (int r = 0; r < counRows; r++)
            {
                // Читаем описание версий. Временно, так как на этом мы
                // теряем байт на строку.
                byte verFlags = br.ReadByte();
                int iVerStart;
                int iVerEnd;
                DataRowState drs;
                switch (verFlags)
                {
                    // Original + Current и они равны!
                    case 0: // DataRowState.Unchanged
                        iVerStart = 0;
                        iVerEnd = 0;
                        drs = DataRowState.Unchanged;
                        break;
                    case 1: // DataRowState.Deleted Только Original
                        iVerStart = 0;
                        iVerEnd = 0;
                        drs = DataRowState.Deleted;
                        break;
                    case 2: // DataRowState.Added Только Current
                        iVerStart = 1;
                        iVerEnd = 1;
                        drs = DataRowState.Added;
                        break;
                    // Original + Current и они НЕ равны!
                    case 3: // DataRowState.Modified
                        iVerStart = 0;
                        iVerEnd = 1;
                        drs = DataRowState.Modified;
                        break;
                    default:
                        throw new ApplicationException(
                            "Недопустимое состояние строки. Сбой при загрузке.");
                }

                // Считываем данные.
                dr = dt.NewRow();
                rows.Add(dr);
                dr.BeginEdit();

                // Считываем версии текущей строки.
                for (int iVetIndex = iVerStart; iVetIndex <= iVerEnd; iVetIndex++)
                {
                    br.Read(byteNull, 0, iBitLenInBytes);
                    bitsNull = new BitArray(byteNull);

                    for (int i = 0; i < iColCount; i++)
                    {
                        if (bitsNull.Get(i))
                        {
                            dr[i] = DBNull.Value;
                            continue;
                        }

                        switch (colTypeCodes[i])
                        {
                            case TypeCode.Boolean: dr[i] = br.ReadBoolean(); break;
                            case TypeCode.Char: dr[i] = br.ReadChar(); break;
                            case TypeCode.SByte: dr[i] = br.ReadSByte(); break;
                            case TypeCode.Byte: dr[i] = br.ReadByte(); break;
                            case TypeCode.Int16: dr[i] = br.ReadInt16(); break;
                            case TypeCode.UInt16: dr[i] = br.ReadUInt16(); break;
                            case TypeCode.Int32: dr[i] = br.ReadInt32(); break;
                            case TypeCode.UInt32: dr[i] = br.ReadUInt32(); break;
                            case TypeCode.Int64: dr[i] = br.ReadInt64(); break;
                            case TypeCode.UInt64: dr[i] = br.ReadUInt64(); break;
                            case TypeCode.Single: dr[i] = br.ReadSingle(); break;
                            case TypeCode.Double: dr[i] = br.ReadDouble(); break;
                            case TypeCode.Decimal: dr[i] = br.ReadDecimal(); break;
                            case TypeCode.DateTime:
                                dr[i] = DateTime.FromFileTime(br.ReadInt64());
                                break;
                            case TypeCode.String: dr[i] = br.ReadString(); break;
                            default:
                                dr[i] = Convert.ChangeType(br.ReadString(),
                                    colTypeCodes[i]);
                                break;
                        }
                    }
                    if (iVetIndex == 0)
                    {
                        dr.AcceptChanges();
                        if (iVerEnd > 0)
                            dr.BeginEdit();
                    }
                }

                if (drs == DataRowState.Deleted)
                    dr.Delete();

                dr.EndEdit();
            }
            dt.EndLoadData();
            return dt;
        }

        public static DataTable DeserializeTable(Stream stream)
        {
            BinaryReader br = new BinaryReader(stream);
            return DeserializeTable(br);
        }

        public static DataSet DeserializeDataSet(Stream stream)
        {
            BinaryReader br = new BinaryReader(stream);
            // Считываем имя DataSet и создаем его...
            DataSet ds = new DataSet(br.ReadString());
            //ds.BeginInit();

            int counTables = br.ReadInt32();

            DataTable dt;
            for (int t = 0; t < counTables; t++)
            {
                dt = DeserializeTable(br);
                ds.Tables.Add(dt);
            }
            return ds;
        }



        // 

        public static DataSet DeserializeDataSet(byte[] array, bool flagZip)
        {
            DataSet ds;
            if (flagZip)
            {
                using (MemoryStream ms = new MemoryStream(array))
                {
                    using (GZipStream zs = new GZipStream(ms, CompressionMode.Decompress))
                    {
                        ds = DataSetSerializer.DeserializeDataSet(zs);
                    }
                }
            }
            else
            {
                using (MemoryStream ms = new MemoryStream(array))
                {
                    ds = DataSetSerializer.DeserializeDataSet(ms);
                }
            }
            return ds;
        }

        public static byte[] SerializeDataSet(DataSet ds, bool flagZip)
        {
            byte[] result;
            using (MemoryStream ms = new MemoryStream())
            {
                if (flagZip)
                {
                    using (GZipStream zs = new GZipStream(ms, CompressionMode.Compress, true))
                    {
                        DataSetSerializer.SerializeDataSet(zs, ds);
                    }
                }
                else
                    DataSetSerializer.SerializeDataSet(ms, ds);
                result = ms.ToArray();
            }
            return result;
        }


    }
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925422
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ты тестируй на нескольких тысячах записей а не на десятке
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36925818
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел GZipStream
Ща потестим
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926114
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasты тестируй на нескольких тысячах записей а не на десятке

Ну потестил, ровсет 45 тыщ записей.
Разница в 600-700 миллисекунд. Не впечатляет.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926326
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabasты тестируй на нескольких тысячах записей а не на десятке

Ну потестил, ровсет 45 тыщ записей.
Разница в 600-700 миллисекунд. Не впечатляет.
какой протокол net.tcp?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926339
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas
какой протокол net.tcp?

http. В локальной сети и БД и WCF-сервис
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926362
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabas
какой протокол net.tcp?

http. В локальной сети и БД и WCF-сервис
странно на net.tcp я еще понял, но на http у меня было быстрее когда тестил
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926364
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попозже сделаю тесты сервиса своего
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36926963
Hug
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hug
Гость
Ребята, я вышел
http://code.google.com/p/protobuf-net/
Вот чем надо се\де\риализовывать
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927083
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HugРебята, я вышел
http://code.google.com/p/protobuf-net/
Вот чем надо се\де\риализовывать

Каков выигрыш, в цифрах?
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927212
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потестил на таблице

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
            testDT = new DataTable("TEST");
            testDT.Columns.Add("A", typeof(string));
            testDT.Columns.Add("B", typeof(string));
            testDT.Columns.Add("B1", typeof(string));
            testDT.Columns.Add("B2", typeof(string));
            testDT.Columns.Add("C", typeof(decimal));
            testDT.Columns.Add("C1", typeof(decimal));
            testDT.Columns.Add("D", typeof(DateTime));
            for (int i = 0; i < 50000; i++)
            {
                var rr = testDT.NewRow();
                rr["A"] = Guid.NewGuid().ToString() + Guid.NewGuid().ToString();
                rr["B"] = Guid.NewGuid().ToString();
                rr["B1"] = Guid.NewGuid().ToString();
                rr["B2"] = null;
                rr["C"] = Convert.ToDecimal(i);
                rr["C1"] = Convert.ToDecimal(i)*20.3M;
                rr["D"] = DateTime.Now;
                testDT.Rows.Add(rr);
            }
            testDT.AcceptChanges();

сервис правда на виртуалке находится а не в реальной сетке
протокол net.tcp c шифрованием сертификатом

TEST1 - стандартный DataTable
TEST2 - rsdn сериализатор без зипа

тест
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
 System.Diagnostics.Debug.Print("");
            System.Diagnostics.Debug.Print("START");
            
            _data.Test1(); // холостой прогон

            var t1 = DateTime.Now;
            for (int i = 0; i < 5; i++)
                _data.Test1();
            var t2 = DateTime.Now;
            System.Diagnostics.Debug.Print("TEST1 " + (t2 - t1).ToString());

            var t3 = DateTime.Now;
            for (int i = 0; i < 5; i++)
                _data.Test2();
            var t4 = DateTime.Now;
            System.Diagnostics.Debug.Print("TEST2 " + (t4 - t3).ToString());

Результат 3х тестов
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
START
TEST1 00:00:09.4795422
TEST2 00:00:05.0442885

START
TEST1 00:00:09.3635356
TEST2 00:00:04.9472829

START
TEST1 00:00:09.4725418
TEST2 00:00:04.8922798

разница в 2 раза, хотя согласен
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927215
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
разница в 2 раза, хотя согласен
не очень большая
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927224
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TEST2 - с зиповкой

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
START
TEST1 00:00:09.4005377
TEST2 00:00:11.6496663

START
TEST1 00:00:09.2965317
TEST2 00:00:10.9346254

START
TEST1 00:00:09.3145328
TEST2 00:00:11.0596325

на одной машине выигрывает стандартный метод (хотя не на много), а вот где канал будет узкий ситуация резка изменится в пользу зипованной передачи (хотя нагрузит сервер побольше, т.к. всё таки зиповать нужно)
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927264
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
размер в байтах после сериализации тестируемой таблицы

Код: plaintext
1.
2.
3.
         6181595 - rsdn
        17863597 - BinaryFormatter
        18663295 - XmlSerializer
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927278
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas


Да, с компрессией у меня разница тоже стала еще меньше.
Насчет объемов - мне это не критично. Клиент у меня тонкий. А WCF сервис и IIS с виртуальным каталогом клиента - они будут как минимум в одной локальной сети.
Вообщем я выводы сделал.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927292
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabas


Да, с компрессией у меня разница тоже стала еще меньше.
Насчет объемов - мне это не критично. Клиент у меня тонкий. А WCF сервис и IIS с виртуальным каталогом клиента - они будут как минимум в одной локальной сети.
Вообщем я выводы сделал.
на самом деле я начал заморачиваться сериализатором, т.к. у меня не получилось с первого раза передать DataTable, тогда я еще не знаю о KnownType и то что имя нужно давать таблице перед передачей (проверил на тестовой безыменной, обломился и до реальных дело не дошло )
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927301
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabashstasbarrabas


Да, с компрессией у меня разница тоже стала еще меньше.
Насчет объемов - мне это не критично. Клиент у меня тонкий. А WCF сервис и IIS с виртуальным каталогом клиента - они будут как минимум в одной локальной сети.
Вообщем я выводы сделал.
на самом деле я начал заморачиваться сериализатором, т.к. у меня не получилось с первого раза передать DataTable, тогда я еще не знаю о KnownType и то что имя нужно давать таблице перед передачей (проверил на тестовой безыменной, обломился и до реальных дело не дошло )

Хм...я не даю таблице никаких имен, если не требуется (когда в ДатаСете не одна таблица).
Все прекрасно передается.
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927320
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hstasbarrabashstasbarrabas


Да, с компрессией у меня разница тоже стала еще меньше.
Насчет объемов - мне это не критично. Клиент у меня тонкий. А WCF сервис и IIS с виртуальным каталогом клиента - они будут как минимум в одной локальной сети.
Вообщем я выводы сделал.
на самом деле я начал заморачиваться сериализатором, т.к. у меня не получилось с первого раза передать DataTable, тогда я еще не знаю о KnownType и то что имя нужно давать таблице перед передачей (проверил на тестовой безыменной, обломился и до реальных дело не дошло )

Хм...я не даю таблице никаких имен, если не требуется (когда в ДатаСете не одна таблица).
Все прекрасно передается.
ну ты из базы ее заполняешь, при Fill имя дается, а я пробовал тупо new DataTable().
...
Рейтинг: 0 / 0
WCF. Эффективнее передать DataSet
    #36927376
hstas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabas
ну ты из базы ее заполняешь, при Fill имя дается, а я пробовал тупо new DataTable().

Согласен
...
Рейтинг: 0 / 0
45 сообщений из 45, показаны все 2 страниц
Форумы / WCF, Web Services, Remoting [игнор отключен] [закрыт для гостей] / WCF. Эффективнее передать DataSet
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]