В связи с тестированием синхронизации между базой данных SQL Server Compact в Windows Phone 8 и базой данных SQL Server (с помощью службы данных WCF, размещенной в IIS), я сделал несколько интересных наблюдений относительно требований к пропускной способности, которыми я хотел бы поделиться.
Я тестирую образец базы данных Chinook , загружая на устройство всю таблицу PlaylistTrack (8715 строк) через службу WCF Data Services. На стороне сервера я использую последнюю версию серверных компонентов WCF Data Services версии 5.3.0. Версия 5.1 или более поздняя включает более новый облегченный формат JSON (просто для сравнения я также включаю размеры для предыдущего формата JSON)
На стороне сервера я создал веб-приложение ASP.NET с сервисом данных WCF, которое предоставляет базу данных Chinook на моем SQL Server через Entity Framework DbContext. Сила служб данных WCF заключается в том, что для этого не требуется кода для настройки. Я настроил свой сервис следующим образом:
public class SyncService : DataService<ChinookEntities> { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { config.UseVerboseErrors = true; //config.SetEntitySetAccessRule("TrackPurchases", EntitySetRights.WriteAppend); config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3; } }
Чтобы получить доступ к службе IIS Express из моего эмулятора Windows Phone 8, я следовал инструкциям здесь: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105) .aspx
Чтобы измерить размер полезной нагрузки, я использую Fiddler2, следуя инструкциям здесь: http://blogs.msdn.com/b/fiddler/archive/2010/10/15/fiddler-and-the-windows-phone -emulator.aspx
Команда служб данных WCF также предоставляет клиента служб данных WCF для Windows Phone , который может использовать ссылку на службу, но у этого клиента есть некоторые серьезные ограничения, которые плохо влияют на потребление полосы пропускания: он поддерживает только формат ATOM на основе XML , но вы можете включить сжатие, как описано здесь: http://blogs.msdn.com/b/astoriateam/archive/2011/10/04/odata-compression-in-windows-phone-7-5-mango.aspx
На стороне клиента я просто использую HttpWebRequest для вызова URL REST и включаю поддержку gzip через библиотеку ICSharpCode.SharpZipLib (например, http://nuget.org/packages/SharpZipLib-WP7/ ).
Вот реализация WebClient:
static public async Task<T> GetData<T>(Uri uri, bool useJson = true, bool version3 = true, bool compress = true) { //uri = new Uri(uri.AbsoluteUri + "&format=json"); HttpWebRequest client = WebRequest.CreateHttp(uri); { if (compress) client.Headers[HttpRequestHeader.AcceptEncoding] = "deflate, gzip"; if (version3) { client.Headers["MaxDataServiceVersion"] = "3.0"; } else { client.Headers["MaxDataServiceVersion"] = "2.0"; } if (useJson) client.Accept = "application/json"; using (WebResponse response = await client.GetResponseAsync()) { string result = await response.GetResponseText(); DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); T resultType; using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(result))) { resultType = (T)serializer.ReadObject(stream); } return resultType; } } } public static async Task<string> GetResponseText(this WebResponse response) { using ( Stream stream = response.IsCompressed() ? new GZipInputStream(response.GetResponseStream()) : response.GetResponseStream()) { using (var reader = new StreamReader(stream)) { return await reader.ReadToEndAsync(); } } } public static bool IsCompressed(this WebResponse response) { return Regex.IsMatch((response.Headers["Content-Encoding"] ?? "") .ToLower(), "(gzip|deflate)"); }
(Я использую Microsoft.Threading.Tasks.Extensions.dll для реализации GetResponseAsync)
Я использую классы DataContext, сгенерированные моим SQL Server Compact Toolbox, для десериализации, с небольшим дополнением — я добавил этот атрибут во все свойства EntitySet <T> и EntityRef <T> (это будет включено в следующий выпуск Toolbox):
[Глобальный :: System.Runtime.Serialization.IgnoreDataMember]
Я звоню по следующему URL: http: // <MyIP>: 2065 / SyncService.svc / PlaylistTracks
Это мой тестовый код:
/ATOM-XML await WebClient.GetData<PlaylistTrackRoot>(uri, false, false, false); //Verbose json await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, false); //Verbose json + gzip await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, true); //Plain json await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, false); //Plain json + gzip await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, true); public class PlaylistTrackRoot { public List<PlaylistTrack> value { get; set; } }
И, наконец, невероятные цифры для загрузки всей таблицы PlaylistTrack с 8715 строками (помните, что ATOM — это формат клиента WCF Data Services по умолчанию)
Тип полезной нагрузки | Размер тела (в байтах) |
ATOM-XML | 9.322.665 (100% — реализация клиента DS по умолчанию) |
JSON (многословно) | 5,016,977 (54%) |
JSON (многословно) + gzip | 328,410 (3,5%) |
JSON (обычный) | 790,845 (8,5%) |
JSON (обычный) + gzip | 43,023 (0,5%) |
Поэтому, прежде чем вы решите использовать WCF Data Services (очень мощная технология), помните: огромная сила — большая ответственность.