W najnowszej wersji WP7 Mango została udostępniona obsługa natywnej bazy danych opartej na silniku SQL CE. W tym wpisie przedstawię prostą bazę do obsługi aplikacji, która nadzoruje spalanie samochodu. Przykład oparty jest na przykładowej aplikacji ToDo z sampli dotyczących WP 7.5.

(Szerzej na ten temat: Windows Phone 7: Using Local Database for Application )

Definicja tabeli

Najpierw tworzymy kontekst danych i tabelę przechowującą dane:

public class ToDoDataContext : DataContext
{
    public ToDoDataContext(string connectionString) : base(connectionString) { }
    public Table<Entries> Items;
}

Klasa Entries będzie naszą tabelą:

[Table]
public class Entries : INotifyPropertyChanged, INotifyPropertyChanging
{
    private int _EntriesId;

    [Column(IsPrimaryKey = true, IsDbGenerated = true,
            DbType = "INT NOT NULL Identity",
            CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int EntriesId
    {
        get { return _EntriesId; }
        set
        {
            if (_EntriesId != value)
            {
                NotifyPropertyChanging("EntriesId");
                _EntriesId = value;
                NotifyPropertyChanged("EntriesId");
            }
        }
    }

    private DateTime _itemDate;

    [Column]
    public DateTime ItemDate
    {
        get { return _itemDate.Date; }
        set
        {
            if (_itemDate != value)
            {
                NotifyPropertyChanging("ItemDate");
                _itemDate = value;
                NotifyPropertyChanged("ItemDate");
            }
        }
    }

    private double _itemDist;

    [Column]
    public double ItemDist { get; set; } // Odległość przejechana

    private double _itemRefuel;

    [Column]
    public double ItemRefuel { get; set; } // Ile zatankowano

    private double _itemFPrice;

    [Column]
    public double ItemFPrice { get; set; } // Cena paliwa za jednostkę

    private string _itemComment;

    [Column]
    public string ItemComment { get; set; } // Komentarz

    private double _itemFuelMill;

    [Column]
    public double ItemFuelMill { get; set; } // Spalanie

    [Column(IsVersion = true)]
    private Binary _version;

    // INotifyPropertyChanged / INotifyPropertyChanging implementation...

    public event PropertyChangedEventHandler PropertyChanged;
    public event PropertyChangingEventHandler PropertyChanging;

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void NotifyPropertyChanging(string propertyName)
    {
        PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
    }
}

ViewModel

Tworzymy Model, który obsługuje dane i zwraca je do mechanizmu Data Binding:

public class ToDoViewModel : INotifyPropertyChanged
{
    private ToDoDataContext toDoDB;

    public ToDoViewModel(string toDoDBConnectionString)
    {
        toDoDB = new ToDoDataContext(toDoDBConnectionString);
    }

    private ObservableCollection<Entries> _allEntriess;
    public ObservableCollection<Entries> AllEntriess
    {
        get { return _allEntriess; }
        set
        {
            _allEntriess = value;
            NotifyPropertyChanged("AllEntriess");
        }
    }

    public void LoadCollectionsFromDatabase()
    {
        var EntriessInDB = from Entries entry in toDoDB.Items
                           orderby entry.ItemDate descending
                           select entry;

        AllEntriess = new ObservableCollection<Entries>(EntriessInDB);
    }

    public void AddEntries(Entries newEntries)
    {
        newEntries.ItemFuelMill = (newEntries.ItemRefuel / newEntries.ItemDist) * 100;
        toDoDB.Items.InsertOnSubmit(newEntries);
        toDoDB.SubmitChanges();
        AllEntriess.Insert(0, newEntries);
    }

    public void DeleteEntries(Entries toDoForDelete)
    {
        AllEntriess.Remove(toDoForDelete);
        toDoDB.Items.DeleteOnSubmit(toDoForDelete);
        toDoDB.SubmitChanges();
    }

    // INotifyPropertyChanged implementation...
}

Inicjalizacja w App.xaml.cs

Referencję do modelu najłatwiej umieścić w App.xaml.cs. WP 7.5 korzysta z mechanizmu Isolated Storage i silnika SQL CE:

private static ToDoViewModel viewModel;
public static ToDoViewModel ViewModel
{
    get { return viewModel; }
}

public App()
{
    UnhandledException += Application_UnhandledException;
    InitializeComponent();
    InitializePhoneApplication();

    string DBConnectionString = "Data Source=isostore:/entries.sdf";

    using (ToDoDataContext db = new ToDoDataContext(DBConnectionString))
    {
        if (db.DatabaseExists() == false)
        {
            db.CreateDatabase();
            db.SubmitChanges();
        }
    }

    viewModel = new ToDoViewModel(DBConnectionString);
    viewModel.LoadCollectionsFromDatabase();
}

Teraz nasza aplikacja ma pełny dostęp do danych. Całkiem sporo kodu jak na obsługę bazy danych, ale cała ta “nadmiarowość” szybko ukaże zalety tego systemu.