From 1078f798a19e5d26b7a6699e4bd11c172e1ff7a0 Mon Sep 17 00:00:00 2001 From: "gu.martinm@gmail.com" Date: Fri, 15 Aug 2014 12:44:20 +0200 Subject: [PATCH] WeatherInformation WP8: database access improvements --- .../WeatherInformation/App.xaml.cs | 14 ---- .../WeatherInformation/MainPage.xaml.cs | 73 +++++++--------- .../WeatherInformation/MapPage.xaml.cs | 98 +++++++++++----------- 3 files changed, 76 insertions(+), 109 deletions(-) diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs b/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs index dfda732..592dcc6 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs +++ b/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs @@ -31,9 +31,6 @@ namespace WeatherInformation // Declare a private variable to store application state. private WeatherData _remoteWeatherData; - // Declare an event for when the application data changes. - public event EventHandler ApplicationDataObjectChanged; - // Declare a public property to access the application data variable. public WeatherData ApplicationDataObject { @@ -43,21 +40,10 @@ namespace WeatherInformation if (value != _remoteWeatherData) { _remoteWeatherData = value; - OnApplicationDataObjectChanged(EventArgs.Empty); } } } - // Create a method to raise the ApplicationDataObjectChanged event. - protected void OnApplicationDataObjectChanged(EventArgs e) - { - EventHandler handler = ApplicationDataObjectChanged; - if (handler != null) - { - handler(this, e); - } - } - /// /// Proporcionar acceso sencillo al marco raíz de la aplicación telefónica. /// diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs b/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs index 9a9658c..b133b16 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs +++ b/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs @@ -22,9 +22,6 @@ namespace WeatherInformation { private MainViewModel _mainViewModel; private bool _isNewPageInstance = false; - // Data context for the local database - private LocationDataContext _locationDB; - private Location _locationItem; // Constructor public MainPage() @@ -33,17 +30,6 @@ namespace WeatherInformation _isNewPageInstance = true; - // Set the event handler for when the application data object changes. - // TODO: doing this, when is the GC going to release this object? I do not think it is going to be able... This is weird... - // Shouldn't I release this even handler when the MainPage is not used anymore. In my case is not a big problem because - // the MainPage should be always active (it is the "mainpage") but if this was not the mainpage... Would the GC be able - // to release this object when the page is not active... I DO NOT THINK SO... - (Application.Current as WeatherInformation.App).ApplicationDataObjectChanged += - new EventHandler(MainPage_ApplicationDataObjectChanged); - - // Connect to the database and instantiate data context. - _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString); - // Código de ejemplo para traducir ApplicationBar //BuildLocalizedApplicationBar(); } @@ -69,26 +55,18 @@ namespace WeatherInformation // and it has remained in memory, this value will continue to be false. _isNewPageInstance = false; - _locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault(); - UpdateApplicationDataUI(); } - protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) + async private void UpdateApplicationDataUI() { - // Call the base method. - base.OnNavigatedFrom(e); - - // Save changes to the database. - // TODO: How does DataContext work? How does it know what data was modified? Is it wasting memory? :( - _locationDB.SubmitChanges(); - - // No calling _locationDB.Dispose? :/ - } + Location locationItem = null; + using (var db = new LocationDataContext(LocationDataContext.DBConnectionString)) + { + locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault(); + } - private void UpdateApplicationDataUI() - { - if (_locationItem == null) + if (locationItem == null) { // Nothing to do. return; @@ -99,7 +77,7 @@ namespace WeatherInformation // TODO: I am setting and getting ApplicationDataObject from different threads!!!! What if I do not see its last value? Do I need synchronization? :/ WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject; if (weatherData != null && - !_locationItem.IsNewLocation && + !locationItem.IsNewLocation && // TODO: NO ESTOY USANDO GetIsolatedStoredData!!!!!! :( (Application.Current as WeatherInformation.App).IsStoredDataFresh()) { @@ -108,17 +86,12 @@ namespace WeatherInformation else { // Otherwise, call the method that loads data. - GetDataAsync(); + await GetDataAsync(locationItem); + // Call UpdateApplicationData on the UI thread. + Dispatcher.BeginInvoke(() => UpdateUI()); } } - // The event handler called when the ApplicationDataObject changes. - void MainPage_ApplicationDataObjectChanged(object sender, EventArgs e) - { - // Call UpdateApplicationData on the UI thread. - Dispatcher.BeginInvoke(() => UpdateUI()); - } - void UpdateUI() { // Set the ApplicationData and ApplicationDataStatus members of the ViewModel @@ -137,7 +110,13 @@ namespace WeatherInformation _mainViewModel.LoadData(weatherData); - _locationItem.IsNewLocation = false; + Location locationItem = null; + using (var db = new LocationDataContext(LocationDataContext.DBConnectionString)) + { + locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault(); + locationItem.IsNewLocation = false; + db.SubmitChanges(); + } } } @@ -152,20 +131,20 @@ namespace WeatherInformation NavigationService.Navigate(new Uri(uri, UriKind.Relative)); } - async private void GetDataAsync() + async private Task GetDataAsync(Location locationItem) { // Gets the data from the web. // TODO: multiple threads writing/reading same data :( - (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync(); + (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync(locationItem); } /// /// Retrieve remote weather data. /// - async public Task LoadDataAsync() + async public Task LoadDataAsync(Location locationItem) { - double latitude = _locationItem.Latitude; - double longitude = _locationItem.Longitude; + double latitude = locationItem.Latitude; + double longitude = locationItem.Longitude; int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber); CustomHTTPClient httpClient = new CustomHTTPClient(); @@ -181,7 +160,11 @@ namespace WeatherInformation string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL); var parser = new ServiceParser(new JsonParser()); - return parser.WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); + var weatherData = parser.WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); + weatherData.City = locationItem.City; + weatherData.Country = locationItem.Country; + + return weatherData; } private void Location_Click(object sender, EventArgs e) diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs b/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs index 1c1575a..1131802 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs +++ b/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs @@ -24,8 +24,6 @@ namespace WeatherInformation { public partial class MapPage : PhoneApplicationPage { - // Data context for the local database - private LocationDataContext _locationDB; // TODO anything better than these two instance fields? :( private string _city; private string _country; @@ -33,17 +31,19 @@ namespace WeatherInformation public MapPage() { InitializeComponent(); - - // Connect to the database and instantiate data context. - _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString); } protected override void OnNavigatedTo(NavigationEventArgs e) { + + Location locationItem = null; + using (var db = new LocationDataContext(LocationDataContext.DBConnectionString)) + { + // Define the query to gather all of the to-do items. + // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location; + locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault(); + } - // Define the query to gather all of the to-do items. - // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location; - var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault(); if (locationItem != null) { GeoCoordinate geoCoordinate = ConvertLocation(locationItem); @@ -52,17 +52,6 @@ namespace WeatherInformation } } - protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) - { - // Call the base method. - base.OnNavigatedFrom(e); - - // Save changes to the database. - _locationDB.SubmitChanges(); - - // No calling _locationDB.Dispose? :/ - } - private async Task GetCurrentLocationAndUpdateMap() { Geolocator geolocator = new Geolocator(); @@ -173,40 +162,49 @@ namespace WeatherInformation // http://stackoverflow.com/questions/4521435/what-specific-values-can-a-c-sharp-double-represent-that-a-sql-server-float-can private void StoreLocation(GeoCoordinate geocoordinate) { - var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault(); - if (locationItem != null) + Location locationItem = null; + using (var db = new LocationDataContext(LocationDataContext.DBConnectionString)) { - locationItem.Latitude = geocoordinate.Latitude; - locationItem.Longitude = geocoordinate.Longitude; - locationItem.Altitude = geocoordinate.Altitude; - locationItem.City = _city ?? ""; - locationItem.Country = _country ?? ""; - locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy; - locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy; - locationItem.Speed = geocoordinate.Speed; - locationItem.Course = geocoordinate.Course; - locationItem.IsNewLocation = true; - locationItem.IsSelected = true; - } - else - { - locationItem = new Location() + // Define the query to gather all of the to-do items. + // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location; + locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault(); + + if (locationItem != null) { - Latitude = geocoordinate.Latitude, - Longitude = geocoordinate.Longitude, - Altitude = geocoordinate.Altitude, - City = _city ?? "", - Country = _country ?? "", - HorizontalAccuracy = geocoordinate.HorizontalAccuracy, - VerticalAccuracy = geocoordinate.VerticalAccuracy, - Speed = geocoordinate.Speed, - Course = geocoordinate.Course, - IsNewLocation = true, - IsSelected = true, - }; + locationItem.Latitude = geocoordinate.Latitude; + locationItem.Longitude = geocoordinate.Longitude; + locationItem.Altitude = geocoordinate.Altitude; + locationItem.City = _city ?? ""; + locationItem.Country = _country ?? ""; + locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy; + locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy; + locationItem.Speed = geocoordinate.Speed; + locationItem.Course = geocoordinate.Course; + locationItem.IsNewLocation = true; + locationItem.IsSelected = true; + } + else + { + locationItem = new Location() + { + Latitude = geocoordinate.Latitude, + Longitude = geocoordinate.Longitude, + Altitude = geocoordinate.Altitude, + City = _city ?? "", + Country = _country ?? "", + HorizontalAccuracy = geocoordinate.HorizontalAccuracy, + VerticalAccuracy = geocoordinate.VerticalAccuracy, + Speed = geocoordinate.Speed, + Course = geocoordinate.Course, + IsNewLocation = true, + IsSelected = true, + }; + + // Add a location item to the local database. + db.Locations.InsertOnSubmit(locationItem); + } - // Add a location item to the local database. - _locationDB.Locations.InsertOnSubmit(locationItem); + db.SubmitChanges(); } } -- 2.1.4