В связи с тестированием синхронизации между базой данных 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 (очень мощная технология), помните: огромная сила — большая ответственность.