sterling for windows phone 7

30
wintellect.com consulting training design debugging Sterling DB for Windows Phone 7 Jeremy Likness Project Manager, Senior Consultant [email protected] Copyright © 2011

Upload: jeremy-likness

Post on 10-May-2015

1.097 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Sterling DB for Windows Phone 7

Jeremy LiknessProject Manager, Senior [email protected]

Copyright © 2011

Page 2: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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.

Consulting & Debugging• Architecture, analysis, and design services• Full lifecycle custom software development• Content creation• Project management• Debugging & performance tuning

Training• On-site instructor-led training• Virtual instructor-led training• Devscovery conferences

Design• User Experience Design• Visual & Content Design• Video & Animation Production

what we do

who we are

how we do it

consulting training debuggingdesign

Page 3: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

• What is Sterling?• Brief History• Stated Goals• Features• Sterling vs. SQL CE• Who is Using Sterling?• Demo: Recipe Application• Questions?

Agenda

Page 4: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 schemas

Page 5: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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)

Page 6: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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)

Page 7: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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”

Page 8: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Sterling DB vs. SQL CEFeature 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 Types

Page 9: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 site

Page 10: Sterling for Windows Phone 7

wintellect.com

demo

consulting training design debugging

recipe application

Page 11: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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; } }}

Page 12: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Define a “Table” and Key

CreateTableDefinition<IngredientModel, int>(i => i.Id)

* Keys are stored in-memory for fast search & lookup (100,000 records w/ Int32 key = 400,000 bytes, < 400Kb memory)

This is provided in the base database class

Type of the “table”

Type of the key

Expression: given the “table” how do I get the key?

Page 13: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 stringCreateTableDefinition<TestCompositeClass,string>(GetCompositeKey)

// method 2 uses a class to represent the key // requires a custom serializerCreateTableDefinition<TestCompositeClass, TestCompositeKeyClass>(k=>new TestCompositeKeyClass(k.Key1, k.Key2, k.Key3, k.Key4))

Page 14: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Define an Index

CreateTableDefinition<FoodModel, int>(f => f.Id)

.WithIndex<FoodModel, string, int>

(IDX_FOOD_NAME, f => f.FoodName)

* Indexes, like keys, are stored in memory so choose wisely!

Extension method for tables

Type of the key

Type of the tableType of the index

Name of the index

Expression: given table, how do I get index?

Page 15: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 registrationDatabase = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>();

Page 16: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Drivers

Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>();

Database = _engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>( new IsolatedStorageDriver());

Database =_engine.SterlingDatabase.RegisterDatabase<RecipeDatabase>( new MyCustomDriver());

Page 17: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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); }

. . .}

Page 18: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Serializers (cont.)

public class TypeSerializer : BaseSerializer { public override void Serialize(object target, BinaryWriter writer) { var type = target as Type; . . . writer.Write(type.AssemblyQualifiedName); } . . .}

Page 19: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Serializers (cont.)

public class TypeSerializer : BaseSerializer { public override object Deserialize(Type type, BinaryReader reader) { return Type.GetType(reader.ReadString()); } . . .}

Page 20: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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; } }}

Page 21: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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;}

Page 22: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Database Setup

// register triggerdatabase.RegisterTrigger(new IdentityTrigger<FoodModel>(database));

// check for existing recordsif (database.Query<CategoryModel, int>().Any()) return;

// truncate tablesdatabase.Truncate(typeof (MeasureModel));database.Truncate(typeof (FoodModel));

// save an entity (handles update and insert)database.Save(measure);

database.Flush(); // ensure keys/indexes are persisted!

Page 23: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Dynamic Tombstoning Supportvar 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, TestNestedInstance

Page 24: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Queries

public IEnumerable<RecipeModel> Recipes{ get { 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}; }}

Dual key handled by tuple

“Covered query” = no deserialization

Page 25: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 deserialization

Page 26: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Queries (cont.)

get{ return from m in App.Database.Query<MeasureModel, int>() orderby m.LazyValue.Value.FullMeasure

select m.LazyValue.Value;}

Second access will retrieve cached value

Lazy value access will de-serialize

Page 27: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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; }}

Page 28: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

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 -> decompress

Page 29: Sterling for Windows Phone 7

wintellect.comconsulting training design debugging

Sterling Resources

• Full source, documentation, discussions, support:http://sterling.codeplex.com/

• User’s Guide (your BEST guide is the unit tests):http://www.sterlingdatabase.com/

• Telerik todolist “How-to” Application:http://www.telerik.com/products/windows-phone/getting-started/todolists.aspx

• My Blog:http://csharperimage.jeremylikness.com/ (@JeremyLikness on Twitter)

Page 30: Sterling for Windows Phone 7

wintellect.com

Questions?

consulting training design debugging

Jeremy LiknessProject Manager, Senior [email protected]