Sterling for Windows Phone 7


Published on

Learn about the lightweight NoSQL database for Windows Phone called Sterling.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • So where is Silverlight today?
  • So where is Silverlight today?
  • So where is Silverlight today?
  • So where is Silverlight today?
  • So where is Silverlight today?
  • So where is Silverlight today?
  • DEMO: Show the TextOverflowDemo project.
  • So where is Silverlight today?
  • Sterling for Windows Phone 7

    1. 1. Sterling DB for Windows Phone 7 Jeremy Likness Project Manager, Senior Consultant Copyright © 2011 jlikness@wintellect.comconsulting training design debugging
    2. 2. what we do consulting training design debugging who we are Founded by top experts on Microsoft – Jeffrey Richter, Jeff Prosise, and John Robbins – we pull out all the stops to help our customers achieve their goals through advanced software-based consulting and training solutions. how we do it Training • On-site instructor-led training Consulting & Debugging • Virtual instructor-led training • Architecture, analysis, and design services • Devscovery conferences • Full lifecycle custom software development • Content creation Design • Project management • User Experience Design • Debugging & performance tuning • Visual & Content Design • Video & Animation Productionconsulting training design debugging
    3. 3. Agenda • What is Sterling? • Brief History • Stated Goals • Features • Sterling vs. SQL CE • Who is Using Sterling? • Demo: Recipe Application • Questions?consulting training design debugging
    4. 4. What is Sterling? “Sterling is a lightweight NoSQL object-oriented database for .Net 4.0, Silverlight 4 and 5, and Windows Phone 7 that works with your existing class structures. Sterling supports full LINQ to Object queries over keys and indexes for fast retrieval of information from large data sets.” • Sterling is not a fully relational database • Sterling is not a document database • Sterling is not a transactional, large scale database • Sterling focuses on specific serialization concerns • Sterling is suitable for local caches • Sterling is suitable for local lightweight data storage or a window of data that synchronizes with a parent server • Sterling is a very easy way to quickly persist existing classes, especially with dynamic schemasconsulting training design debugging
    5. 5. Brief History • Many customers were working with Silverlight 4 because of the ability to have the out-of-browser (OOB) offline mode • Found that existing serialization strategies tended to be shallow, invasive, and lacked query capabilities • Used various techniques such as synchronizing lists as individual items and then providing a “keyed” index or view into the list • Built first version of Sterling to abstract this and introduce concept of both indexes and foreign keys to serialization • Windows Phone 7 was released and Sterling filled the need for a local database • Was able to port over to run on Windows Phone 7 within hours (mostly just needed to stub Silverlight 3 – Silverlight 4 differences) • Popularity grew and requests came in for in-memory, .NET, etc. versions, (1.5 release)consulting training design debugging
    6. 6. Stated Goals • Non-intrusive – don’t modify your classes or derive from some base class just to be able to use it. • Lightweight – current DLL is < 100 kilobytes. • Flexible – extensions for adding compression, encryption, triggers, custom serializers, etc. • Portable – same API in browser, on desktop/server and in phone (possible Mono versions in the pipeline)consulting training design debugging
    7. 7. Features • Recurses complex object graphs and handles cycle conditions • Handles public properties and fields (including interface/abstract) • Ability to suppress serialization of fields, properties, and types • Flexible “is dirty” support to avoid saving full graph • Driver-model allowing in-memory, isolated storage versions for phone • Easy configuration – specify table type, key type, and how to resolve the key or index • “Save as” allows saving derived types to base class • Full “foreign key” allowing child objects to serialize to separate tables • Binary serialization for much smaller footprint • Extensions for serialization, compression, encryption, etc. • Trigger support • Database backup and restore • LINQ to Object queries on in-memory keys, indexes, “records”consulting training design debugging
    8. 8. Sterling DB vs. SQL CE Feature Sterling DB SQL CE Database Backup Database Create Insert Many Items Delete Items Truncate Table Search Substring Search Key Search Key w/ Joins Search Non-Idx Col Search Index Serialize Full Graph Dynamic Typesconsulting training design debugging
    9. 9. Who is Using Sterling? • HealthCaddy • Sharp DropBox Client for .NET (WP7 Library) • Expense Report Tracker • Horse Vaccine Tracker • Stacks for Instapaper • SmugSeven • RunKeeper • MyReiningScores • Many more that you can read about on the Sterling siteconsulting training design debugging
    10. 10. demo recipe applicationconsulting training design debugging
    11. 11. Define your Database public class RecipeDatabase : BaseDatabaseInstance { protected override List<ITableDefinition> _RegisterTables() { return new List<ITableDefinition>(); } /// this is optional, will default to full type name public override string Name { get { return STERLING_RECIPES; } } }consulting training design debugging
    12. 12. Define a “Table” and Key This is provided in the base database class Type of the “table” CreateTableDefinition<IngredientModel, int>(i => i.Id) Type of the key Expression: given the “table” how do I get the key? * Keys are stored in-memory for fast search & lookup (100,000 records w/ Int32 key = 400,000 bytes, < 400Kb memory)consulting training design debugging
    13. 13. Composite Keys public static string GetCompositeKey(TestCompositeClass testClass) { if (testClass == null) return string.Empty; return string.Format("{0}-{1}-{2}-{3}", testClass.Key1, testClass.Key2, testClass.Key3, testClass.Key4); } // method 1 uses a string CreateTableDefinition<TestCompositeClass,string>(GetCompositeKey) // method 2 uses a class to represent the key // requires a custom serializer CreateTableDefinition<TestCompositeClass, TestCompositeKeyClass>(k=> new TestCompositeKeyClass(k.Key1, k.Key2, k.Key3, k.Key4))consulting training design debugging
    14. 14. Define an Index CreateTableDefinition<FoodModel, int>(f => f.Id) Extension method for tables Type of the table Type of the index .WithIndex<FoodModel, string, int> Type of the key (IDX_FOOD_NAME, f => f.FoodName) Expression: given table, how do I get index? Name of the index * Indexes, like keys, are stored in memory so choose wisely!consulting training design debugging
    15. 15. Activating the Engine/Databases _engine = new SterlingEngine(); // register custom serializers _engine.SterlingDatabase.RegisterSerializer<TypeSerializer>(); // register any loggers (or use the default logger) _logger = new SterlingDefaultLogger(SterlingLogLevel.Information); // activate the engine – now ready for your databases _engine.Activate(); // here is a database registration Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>();consulting training design debugging
    16. 16. Drivers Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>(); Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>( new IsolatedStorageDriver()); Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>( new MyCustomDriver());consulting training design debugging
    17. 17. Serializers // required for any keys that are not core value types // required for any classes that are not easily de-serialized // (i.e. no parameterless constructor, etc. – e.g. “Type” class) public class TypeSerializer : BaseSerializer { public override bool CanSerialize(Type targetType) { return typeof (Type).IsAssignableFrom(targetType); } . . . }consulting training design debugging
    18. 18. Serializers (cont.) public class TypeSerializer : BaseSerializer { public override void Serialize(object target, BinaryWriter writer) { var type = target as Type; . . . writer.Write(type.AssemblyQualifiedName); } . . . }consulting training design debugging
    19. 19. Serializers (cont.) public class TypeSerializer : BaseSerializer { public override object Deserialize(Type type, BinaryReader reader) { return Type.GetType(reader.ReadString()); } . . . }consulting training design debugging
    20. 20. Triggers public class IdentityTrigger<T> : BaseSterlingTrigger<T,int> where T: class, IBaseModel, new() { private static int _idx = 1; public IdentityTrigger(ISterlingDatabaseInstance database) { // if a record exists, set it to the highest value plus 1 if (database.Query<T,int>().Any()) { _idx = database.Query<T, int>().Max(key => key.Key) + 1; } } }consulting training design debugging
    21. 21. Triggers (cont.) public override bool BeforeSave(T instance) { if (instance.Id < 1) { instance.Id = _idx++; } return true; } public override void AfterSave(T instance) { // set dirty flag? return; }consulting training design debugging
    22. 22. Database Setup // register trigger database.RegisterTrigger(new IdentityTrigger<FoodModel>(database)); // check for existing records if (database.Query<CategoryModel, int>().Any()) return; // truncate tables database.Truncate(typeof (MeasureModel)); database.Truncate(typeof (FoodModel)); // save an entity (handles update and insert) database.Save(measure); database.Flush(); // ensure keys/indexes are persisted!consulting training design debugging
    23. 23. Dynamic Tombstoning Support var tombstone = new TombstoneModel {SyncType = typeof (IRecipeViewModel)}; tombstone.State.Add(RECIPE_ID, _recipe.Id); Tombstone.State.Add("ComplexType", MyComplexType); database.Save(tombstone); // handles recursion into sub-lists and dictionaries // further recursion on types // will not choke on cycles // take a look at tests for examples // TestCycle, TestEnum, TestInterfaceProperty, TestNestedInstanceconsulting training design debugging
    24. 24. Queries public IEnumerable<RecipeModel> Recipes { get Dual key handled by tuple { return from r in App.Database.Query<RecipeModel, int, string, int>(RecipeDatabase.IDX_RECIPE_CATEGORYID_NAME) where r.Index.Item1.Equals(CurrentCategory == null ? 0 : CurrentCategory.Id) orderby r.Index.Item2 select new RecipeModel {Id = r.Key, Name = r.Index.Item2}; } } “Covered query” = no deserializationconsulting training design debugging
    25. 25. Queries (cont.) get { if (string.IsNullOrEmpty(_foodText)) { return Enumerable.Empty<FoodModel>(); } var foodTextLower = _foodText.ToLower(); return from f in App.Database.Query<FoodModel, string, int>(RecipeDatabase.IDX_FOOD_NAME) where f.Index.ToLower().Contains(foodTextLower) orderby f.Index select new FoodModel {Id = f.Key, FoodName = f.Index}; } “Covered query” = no deserializationconsulting training design debugging
    26. 26. Queries (cont.) get { return from m in App.Database.Query<MeasureModel, int>() orderby m.LazyValue.Value.FullMeasure Lazy value access will de-serialize select m.LazyValue.Value; } Second access will retrieve cached valueconsulting training design debugging
    27. 27. Compression/Encryption public class ByteInterceptor : BaseSterlingByteInterceptor { override public byte[] Save(byte[] sourceStream) { var retVal = new byte[sourceStream.Length]; for (var x = 0; x < sourceStream.Length; x++) { retVal[x] = (byte)(sourceStream[x] ^ 0x80); // xor } return retVal; } override public byte[] Load(byte[] sourceStream) { var retVal = new byte[sourceStream.Length]; for (var x = 0; x < sourceStream.Length; x++) { retVal[x] = (byte)(sourceStream[x] ^ 0x80); // xor } return retVal; } }consulting training design debugging
    28. 28. Compression/Encryption (cont.) databaseInstance.RegisterInterceptor<ByteInterceptor>(); databaseInstance.RegisterInterceptor<ByteInterceptor2>(); // called in order of registration on save // called in reverse order on load // i.e. compression -> encrypt, then decrypt -> decompressconsulting training design debugging
    29. 29. Sterling Resources • Full source, documentation, discussions, support: • User’s Guide (your BEST guide is the unit tests): • Telerik todolist “How-to” Application: phone/getting-started/todolists.aspx • My Blog: (@JeremyLikness on Twitter)consulting training design debugging
    30. 30. Questions? Jeremy Likness Project Manager, Senior Consultant jlikness@wintellect.comconsulting training design debugging