Sterling database is a NoSQL object-oriented database product. It can be used not only for Silverlight for Desktop, but also for Windows Phone. I recently selected Sterling as the database for a Windows Phone project, mainly because of two reasons: 1. Support for Linq query 2. comprehensive functionality
You can refer to the User Guide for how to use Sterling to access data. Some problems have been encountered in the actual project. Several precautions are as follows:
1. The index field value cannot be null. Otherwise, an exception occurs during saving. This is not mentioned in the Index section of the User Guide. The disussion on CodePlex mentions a solution: Specify the default value when defining the Index. For example, index_GroceryItem_Rating
protected override System.Collections.Generic.List<ITableDefinition> _RegisterTables() { return new List<ITableDefinition> { CreateTableDefinition<Tombstone,bool>(c=>true), CreateTableDefinition<Grocery,int>(g=> g.Id), CreateTableDefinition<GroceryItem,int>(x=> x.Id)
.WithIndex<GroceryItem,int,int>(index_GroceryItem_GroceryId, x=> x.GroceryId)
.WithIndex<GroceryItem,string,int>(index_GroceryItem_Rating, x=> x.Rating??
string.Empty)
//index cannot be null, so set default value if null
.WithIndex<GroceryItem,int,int>(index_GroceryItem_Quantity, x=> x.Quantity) }; }
2. Use Flush after saving to avoid damage to the primary key and index of the database after the program ends abnormally. For more information, see Save in User Guide.
3. Auto Identity-to implement Auto-incrementing primary keys, you need to implement a trigger
public class GroceryTrigger : BaseSterlingTrigger<Grocery, int> { private int _nextId; public GroceryTrigger(int nextId) { _nextId = nextId; } public override bool BeforeSave(Grocery instance) { if (instance.Id < 1) { instance.Id = _nextId++; } return true; } public override void AfterSave(Grocery instance) { return; } public override bool BeforeDelete(int key) { return true; } }
And initialized when the program is started or activated (Application_Launching and Application_Activated events ).
private void ActivateEngine() { _engine = new SterlingEngine(); _logger = new SterlingDefaultLogger(SterlingLogLevel.Information); _engine.Activate(); _database = _engine.SterlingDatabase.RegisterDatabase<GroceryDatabase>(); int maxGroceryListId = _database.Query<Grocery, int>().Any() ? (from id in _database.Query<Grocery, int>() select id.Key).Max() + 1 : 1; _database.RegisterTrigger<Grocery, int>(new GroceryDatabase.GroceryTrigger(maxGroceryListId)); }
4. Side effects of Caching. If you use the Query statement instead of the Load statement to obtain the object, the obtained object is the Cache version instead of the version saved by the database. If the modification to the Cache version has not been submitted through the Save operation, the Cache version is inconsistent with the database version. If you don't pay attention to this, you may encounter unexpected bugs. For example, the view model of a page loads data using the following Query statement:
var items = (from item in App.Database.Query<GroceryItem, int, int>(GroceryDatabase.index_GroceryItem_GroceryId) where item.Index == groceryId select item).ToList();
The user modifies some data values through the UI operation. There is a Save button and a Cancel button in the page. If you do not want to Save it, select Cancel, and the data modification is not submitted. However, the value in the Cache has changed. If you re-enter the page and execute the preceding Query statement, the version in the Cache is obtained, which is inconsistent with expectation.
The solution is to Load data through the Load statement to ensure that the database version is loaded each time:
var itemIds = (from x in App.Database.Query<GroceryItem, int, int>(GroceryDatabase.index_GroceryItem_GroceryId) where x.Index == groceryId select x.LazyValue.Value.Id).ToList(); foreach (int id in itemIds) { var item = App.Database.Load<GroceryItem>(id); Items.Add(item); }