From 99e6c523e573d4ae44cc61f26ce8a4d5919a59e0 Mon Sep 17 00:00:00 2001 From: "gu.martinm@gmail.com" Date: Mon, 11 Aug 2014 01:12:04 +0200 Subject: [PATCH] WeatherInformation WP8: trying to to work with database --- .../WeatherInformation/App.xaml.cs | 147 +--------- .../WeatherInformation/MainPage.xaml.cs | 196 ++++++++++++-- .../WeatherInformation/MapPage.xaml | 10 +- .../WeatherInformation/MapPage.xaml.cs | 198 +++++++------- .../WeatherInformation/Model/Location.cs | 296 +++++++++++++++++++++ .../Model/LocationDataContext.cs | 23 ++ .../Model/Services/StoredLocation.cs | 195 -------------- .../WeatherInformation/Model/WeatherData.cs | 4 + .../Resources/AppResources.Designer.cs | 36 +-- .../Resources/AppResources.es.resx | 16 +- .../Resources/AppResources.es.xlf | 20 +- .../Resources/AppResources.qps-ploc.xlf | 20 +- .../WeatherInformation/Resources/AppResources.resx | 14 +- .../WeatherInformation/SelectedDatePage.xaml.cs | 2 +- .../WeatherInformation/ViewModels/MainViewModel.cs | 4 +- .../ViewModels/SelectedDateViewModel.cs | 4 +- .../WeatherInformation/WeatherInformation.csproj | 3 +- 17 files changed, 690 insertions(+), 498 deletions(-) create mode 100644 WindowsPhone/WeatherInformation/WeatherInformation/Model/Location.cs create mode 100644 WindowsPhone/WeatherInformation/WeatherInformation/Model/LocationDataContext.cs delete mode 100644 WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/StoredLocation.cs diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs b/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs index 53ccf9b..0d1fb52 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs +++ b/WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs @@ -81,6 +81,16 @@ namespace WeatherInformation // Inicialización del idioma InitializeLanguage(); + // Create the database if it does not exist. + using (LocationDataContext db = new LocationDataContext(LocationDataContext.DBConnectionString)) + { + if (db.DatabaseExists() == false) + { + //Create the database + db.CreateDatabase(); + } + } + // Mostrar información de generación de perfiles gráfica durante la depuración. if (Debugger.IsAttached) { @@ -102,143 +112,6 @@ namespace WeatherInformation } } - public void GetDataAsync() - { - // Call the GetData method on a new thread. - // TODO: Are there too many threads? HttpClient is going to create more... (threadpools and stuff like that...) - Thread t = new Thread(new ThreadStart(GetData)); - t.Start(); - } - - async private void GetData() - { - // Check to see if data exists in isolated storage and see if the data is fresh. - WeatherData weatherData = GetIsolatedStoredData(); - - if ((weatherData != null) && IsStoredDataFresh() && !StoredLocation.IsNewLocation) - { - ApplicationDataObject = weatherData; - } - else - { - // Otherwise, it gets the data from the web. - ApplicationDataObject = await LoadDataAsync(); - } - } - - private bool IsStoredDataFresh() - { - // Check to see if the data is fresh. - // This example uses 30 seconds as the valid time window to make it easy to test. - // Real apps will use a larger window. - - // Check the time elapsed since data was last saved to isolated storage. - TimeSpan TimeSinceLastSave = TimeSpan.FromSeconds(0); - if (IsolatedStorageSettings.ApplicationSettings.Contains("DataLastSavedTime")) - { - DateTime dataLastSaveTime = (DateTime)IsolatedStorageSettings.ApplicationSettings["DataLastSavedTime"]; - TimeSinceLastSave = DateTime.Now - dataLastSaveTime; - } - - if (TimeSinceLastSave.TotalSeconds < 30) - { - return true; - } - - return false; - } - - private WeatherData GetIsolatedStoredData() - { - string JSONRemoteCurrentWeather = null; - string JSONRemoteForecastWeather = null; - - using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) - { - if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") && - isoStore.FileExists("JSONRemoteForecastWeatherFile.txt")) - { - using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open)) - using (StreamReader sr = new StreamReader(file)) - { - // This method loads the data from isolated storage, if it is available. - JSONRemoteCurrentWeather = sr.ReadLine(); - } - - using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open)) - using (StreamReader sr = new StreamReader(file)) - { - // This method loads the data from isolated storage, if it is available. - JSONRemoteForecastWeather = sr.ReadLine(); - } - } - } - - if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather)) - { - return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); - } - - return null; - } - - /// - /// Retrieve remote weather data. - /// - async public Task LoadDataAsync() - { - double latitude = StoredLocation.CurrentLatitude; - double longitude = StoredLocation.CurrentLongitude; - int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber); - - CustomHTTPClient httpClient = new CustomHTTPClient(); - - string formattedForecastURL = String.Format( - CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapForecast, - AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber); - string JSONRemoteForecastWeather = await httpClient.GetWeatherDataAsync(formattedForecastURL); - - string formattedCurrentURL = String.Format( - CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapCurrent, - AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber); - string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL); - - return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); - } - - private ForecastWeather ForecastWeatherParser(string remoteForecastWeatherData) - { - ServiceParser parser = new ServiceParser(new JsonParser()); - return parser.GetForecastWeather(remoteForecastWeatherData); - } - - private CurrentWeather CurrentWeatherParser(string remoteCurrentWeatherData) - { - ServiceParser parser = new ServiceParser(new JsonParser()); - return parser.GetCurrentWeather(remoteCurrentWeatherData); - } - - private WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather) - { - if (string.IsNullOrEmpty(JSONRemoteForecastWeather)) - { - throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather"); - } - if (string.IsNullOrEmpty(JSONRemoteCurrentWeather)) - { - throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather"); - } - - return new WeatherData - { - JSONRemoteCurrent = JSONRemoteCurrentWeather, - JSONRemoteForecast = JSONRemoteForecastWeather, - RemoteCurrent = CurrentWeatherParser(JSONRemoteCurrentWeather), - RemoteForecast = ForecastWeatherParser(JSONRemoteForecastWeather), - WasThereRemoteError = false - }; - } - // no way of moving temporary file atomically with IsolatedStorageFile. LINUX OWNS MICROSOFT. private void SaveDataToIsolatedStorage(string fileName, string value) { diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs b/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs index 9f244f5..a7e3d63 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs +++ b/WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs @@ -1,5 +1,6 @@ using Microsoft.Phone.Controls; using System; +using System.Linq; using System.Globalization; using System.IO.IsolatedStorage; using System.Windows; @@ -9,6 +10,11 @@ using WeatherInformation.Model; using WeatherInformation.Model.Services; using WeatherInformation.Resources; using WeatherInformation.ViewModels; +using System.Threading; +using System.Threading.Tasks; +using WeatherInformation.Model.ForecastWeatherParser; +using WeatherInformation.Model.CurrentWeatherParser; +using WeatherInformation.Model.JsonDataParser; namespace WeatherInformation { @@ -16,6 +22,9 @@ namespace WeatherInformation { private MainViewModel _mainViewModel; private bool _isNewPageInstance = false; + // Data context for the local database + private LocationDataContext _locationDB; + private Location _locationItem; // Constructor public MainPage() @@ -32,7 +41,10 @@ namespace WeatherInformation (Application.Current as WeatherInformation.App).ApplicationDataObjectChanged += new EventHandler(MainPage_ApplicationDataObjectChanged); + // Connect to the database and instantiate data context. + _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString); + _locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault(); // Código de ejemplo para traducir ApplicationBar //BuildLocalizedApplicationBar(); } @@ -61,23 +73,37 @@ namespace WeatherInformation UpdateApplicationDataUI(); } + 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 void UpdateApplicationDataUI() { - if (StoredLocation.IsThereCurrentLocation) + if (_locationItem == null) { - // If the application member variable is not empty, - // set the page's data object from the application member variable. - // 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 && !StoredLocation.IsNewLocation) - { - UpdateUI(); - } - else - { - // Otherwise, call the method that loads data. - (Application.Current as WeatherInformation.App).GetDataAsync(); - } + // Nothing to do. + return; + } + + // If the application member variable is not empty, + // set the page's data object from the application member variable. + // 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 && IsStoredDataFresh()) + { + UpdateUI(); + } + else + { + // Otherwise, call the method that loads data. + GetDataAsync(); } } @@ -99,14 +125,18 @@ namespace WeatherInformation { MessageBox.Show( AppResources.NoticeThereIsNotCurrentLocation, - AppResources.AskForLocationConsentMessageBoxCaption, + AppResources.UnavailableAutomaticCurrentLocationMessageBox, MessageBoxButton.OK); return; } _mainViewModel.LoadData(weatherData); - StoredLocation.IsNewLocation = false; + var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault(); + if (locationItem != null) + { + locationItem.IsNewLocation = false; + } } } @@ -121,6 +151,140 @@ namespace WeatherInformation NavigationService.Navigate(new Uri(uri, UriKind.Relative)); } + public void GetDataAsync() + { + // Call the GetData method on a new thread. + // TODO: Are there too many threads? HttpClient is going to create more... (threadpools and stuff like that...) + Thread t = new Thread(new ThreadStart(GetData)); + t.Start(); + } + + async private void GetData() + { + // Check to see if data exists in storage and see if the data is fresh. + WeatherData weatherData = GetIsolatedStoredData(); + + if ((weatherData != null) && IsStoredDataFresh() && !_locationItem.IsNewLocation) + { + (Application.Current as WeatherInformation.App).ApplicationDataObject = weatherData; + } + else + { + // Otherwise, it gets the data from the web. + (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync(); + } + } + + /// + /// Retrieve remote weather data. + /// + async public Task LoadDataAsync() + { + double latitude = _locationItem.Latitude; + double longitude = _locationItem.Longitude; + int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber); + + CustomHTTPClient httpClient = new CustomHTTPClient(); + + string formattedForecastURL = String.Format( + CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapForecast, + AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber); + string JSONRemoteForecastWeather = await httpClient.GetWeatherDataAsync(formattedForecastURL); + + string formattedCurrentURL = String.Format( + CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapCurrent, + AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber); + string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL); + + return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); + } + + // ESTE METODO ERA PARA CARGAR LOS DATOS JSON NO LOS DE LA BASE DE DATOS. HAY QUE REPENSAR ESTO :( + private bool IsStoredDataFresh() + { + // Check to see if the data is fresh. + // This example uses 30 seconds as the valid time window to make it easy to test. + // Real apps will use a larger window. + + // Check the time elapsed since data was last saved to storage. + DateTime dataLastSaveTime = _locationItem.StoredTime; + TimeSpan timeSinceLastSave = DateTime.Now - dataLastSaveTime; + + if (timeSinceLastSave.TotalSeconds < 30) + { + return true; + } + + return false; + } + + private WeatherData GetIsolatedStoredData() + { + string JSONRemoteCurrentWeather = null; + string JSONRemoteForecastWeather = null; + + using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") && + isoStore.FileExists("JSONRemoteForecastWeatherFile.txt")) + { + using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open)) + using (StreamReader sr = new StreamReader(file)) + { + // This method loads the data from isolated storage, if it is available. + JSONRemoteCurrentWeather = sr.ReadLine(); + } + + using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open)) + using (StreamReader sr = new StreamReader(file)) + { + // This method loads the data from isolated storage, if it is available. + JSONRemoteForecastWeather = sr.ReadLine(); + } + } + } + + if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather)) + { + return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather); + } + + return null; + } + + private ForecastWeather ForecastWeatherParser(string remoteForecastWeatherData) + { + ServiceParser parser = new ServiceParser(new JsonParser()); + return parser.GetForecastWeather(remoteForecastWeatherData); + } + + private CurrentWeather CurrentWeatherParser(string remoteCurrentWeatherData) + { + ServiceParser parser = new ServiceParser(new JsonParser()); + return parser.GetCurrentWeather(remoteCurrentWeatherData); + } + + private WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather) + { + if (string.IsNullOrEmpty(JSONRemoteForecastWeather)) + { + throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather"); + } + if (string.IsNullOrEmpty(JSONRemoteCurrentWeather)) + { + throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather"); + } + + return new WeatherData + { + JSONRemoteCurrent = JSONRemoteCurrentWeather, + JSONRemoteForecast = JSONRemoteForecastWeather, + RemoteCurrent = CurrentWeatherParser(JSONRemoteCurrentWeather), + RemoteForecast = ForecastWeatherParser(JSONRemoteForecastWeather), + WasThereRemoteError = false + }; + } + private void Location_Click(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/MapPage.xaml", UriKind.Relative)); diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml b/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml index 2aec0e7..5c4bd37 100644 --- a/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml +++ b/WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml @@ -20,6 +20,7 @@ + @@ -32,7 +33,14 @@ -