Local database with SQLite in Windows phone 8 - c#

I create a test app with a local database in Windows phone 8 but I get error and my project can't create my sqlite database
Can you help me ?
Runtime error is this :
An exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.ni.dll but was not handled in user code
Additional information: Exception has been thrown by the target of an invocation.
In this line : val = m.GetValue( obj , null ) ;
Person class :
namespace PhoneApp4
{
public class person
{
[SQLite.AutoIncrement , SQLite.PrimaryKey]
public int ID { get; set; }
public string FullName { get; set; }
}
}
mainpage.xaml.cs:
namespace PhoneApp4
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void BTO_save_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite"), true);
person person = new person
{
FullName = TB_save.Text
};
await conn.InsertAsync(person);
}
private async void BTO_search_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "people.db"), true);
var query = conn.Table<person>().Where(x => x.ID == Convert.ToInt32(TB_search.Text));
var result = await query.ToListAsync();
foreach (var item in result)
{
LB_search.Items.Add(item.ID.ToString() + " " + item.FullName.ToString());
}
}
app.xaml.cs:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
if (FileExists("dbsqlite.sqlite").Result)
{
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
if (!FileExists("dbsqlite.sqlite").Result)
{
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
}

See this sample
http://code.msdn.microsoft.com/SQLite-for-Windows-Phone-8-8ff3beaf
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
try
{
await ApplicationData.Current.LocalFolder.GetFileAsync("UniversityDB.db");
Connection = new SQLiteAsyncConnection("UniversityDB.db");
}
catch (FileNotFoundException)
{
DataService.CreateDbAsync();
}
}
and
public static async void CreateDbAsync()
{
App.Connection = new SQLiteAsyncConnection("UniversityDB.db");
var universityTask = App.Connection.CreateTableAsync<University>();
var studentTask = App.Connection.CreateTableAsync<Student>();
await Task.WhenAll(new Task[] { universityTask, studentTask });
}

Related

Is there a way to create a timeout to an attempt to connection with Xamarin.Forms?

I'm trying to develop a warning if I try to connect to a specific SSID and some waiting time has passed. I've tried with a Timer class but there is some issues with Task and Threads I can't resolve.
This is my Wifi class in Xamarin.Droid
public class Wifi : Iwifi
{
private Context context;
private static WifiManager _manager;
private MyReceiver _receiver;
public void Initialize()
{
context = Android.App.Application.Context;
_manager = (WifiManager)context.GetSystemService(Context.WifiService);
_receiver = new MyReceiver();
}
public void Register()
{
IntentFilter intents = new IntentFilter();
intents.AddAction(WifiManager.ScanResultAction);
intents.AddAction(WifiManager.NetworkStateChangedAction);
context.RegisterReceiver(_receiver, intents);
}
public void Unregister()
{
context.UnregisterReceiver(_receiver);
}
public void ScanWirelessDevices()
{
_manager.StartScan();
}
public string GetConnectionSSID()
{
return _manager.ConnectionInfo.SSID;
}
public void ConnectToSSID(string SSID, string pwd)
{
if (!_manager.IsWifiEnabled)
{
_manager.SetWifiEnabled(true);
}
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.Ssid = '"' + SSID + '"';
if (pwd.Empty)
{
wifiConfiguration.AllowedKeyManagement.Set((int)KeyManagementType.None);
}
else
{
//Configuration for protected Network
}
var addNet = _manager.AddNetwork(wifiConfiguration);
if (addNet == -1)
{
_manager.Disconnect();
_manager.EnableNetwork(addNet, true);
_manager.Reconnect();
return;
}
var list = _manager.ConfiguredNetworks;
foreach (WifiConfiguration conf in list)
{
if (conf.Ssid.Equals('"' + SSID + '"'))
{
_manager.Disconnect();
_manager.EnableNetwork(conf.NetworkId, true);
_manager.Reconnect();
return;
}
}
}
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(WifiManager.ScanResultAvailableAction))
{
IList<ScanResult> scanResult = _manager.ScanResult;
App.Networks.NetworksList.Clear();
foreach (ScanResult result in scanResult)
{
App.Networks.NetworksList.Add(result.Ssid);
}
}
}
}
}
Then this is a part of App class in Xamarin.Forms
public partial class App: Application
{
private static ...
.
.
.
private static string _selectedSSID;
private static MainDetail _pageDetail;
public static IWifi WifiManager { get; } = DependencyService.Get<Iwifi>();
public static string SelectedSSID { get { return _selectedSSID; } set { _selectedSSID = value; } }
public static MainDetail PageDetail { get { return _pageDetail; } }
public App()
{
InitializeComponent();
WifiManager.Initialize();
WifiManager.Register();
InitViews();
MainPage = _mainPage;
Connectivity.ConnectivityChanged += NetworkEvents;
NetSearch();
}
.
.
.
public void NetSearch()
{
Task.Run(async () =>
{
while (true)
{
WifiManager.ScanWirelessDevices();
await Task.Delay(Utility.SCAN_WIFI_TIMER); //waiting 31000 milliseconds because of Scanning throttling
}
});
}
public void NetworkEvents(object sender, ConnectivityChangedEventArgs e)
{
MainMaster master = (MainMaster)_mainPage.Master;
if (e.NetworkAccess == NetworkAccess.Unknown)
{
Debug.WriteLine("Network Access Unknown " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.None)
{
Debug.WriteLine("Network Access None " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Local)
{
Debug.WriteLine("Network Access Local " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Internet)
{
if(selectedSSID == Wifimanager.GetConnectionInfo())
{
//WE CONNECTED!!
//Now I want to stop the Timeout Timer to attempt
}
}
if (e.NetworkAccess == NetworkAccess.ConstrainedInternet)
{
Debug.WriteLine("Network Access Constrainde Internet " + e.ToString());
}
}
}
And part of Detail page class in which I start the event of connection and where I want to start also the timeout timer
public partial class MainDetail : ContentPage
{
.
.
.
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
//Now the timer should start.
//And call PageDetail.ActivityIndicator(false) and warning the user if the timeout go to 0.
listView.SelectedItem = null;
}
}
I tried with the Timers Timer class but doesn't work.. any suggestion?
Ok I figured a solution! Instead of using Thread and Task, I used Device.StartTimer.
In the event on the DetailPage I wrote:
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
Device.StartTimer(TimeSpan.FromSeconds(10), () => //Waiting 10 second then if we are not connected fire the event.
{
Device.BeginInvokeOnMainThread(() =>
{
if (App.IsLogout) //variable I use to check if I can do the logout or not
{
ActivityIndicator(false);
App.SelectedSSID = "";
//My message to users "Fail to connect"
}
});
return false;
});
listView.SelectedItem = null;
}

Edit UI using a Plugin

I built off of this code: https://www.codeproject.com/Articles/1052356/Creating-a-Simple-Plugin-System-with-NET and I turned it into a windows form. However I can't figure out how I can make it edit the UI from the DLL. I created a controller class with the following code:
public RichTextBox console;
public void WriteToRichTextBox(dynamic text, RichTextBox control)
{
control.AppendText(text + "\n");
}
` However, I can't figure out how to make them share the same controller class.
Form Code:
PluginLoader loader;
Controller controller;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
//Let the user fill in an plugin name
string line = textBox1.Text;
string name = line.Split(new char[] { ' ' }).FirstOrDefault();
IPlugin plugin = PluginLoader.Plugins.Where(p => p._pluginName
== name).FirstOrDefault();
if (plugin != null)
{
//If the plugin is found, execute it
plugin.PluginLaunched();
}
else
{
Log(string.Format("No plugin found with name '{0}'", name));
}
}
catch (Exception ex)
{
Log(string.Format("Caught exception: {0}", ex.Message));
}
textBox1.Clear();
}
private void Log(string text)
{
richTextBox1.AppendText(text + "\n");
}
private void Form1_Load(object sender, EventArgs e)
{
Log("Started plugin app..");
try
{
loader = new PluginLoader();
controller = new Controller();
loader.LoadPlugins();
controller.console = richTextBox1;
}
catch (Exception ex)
{
Log(string.Format("Plugins couldn't be loaded: {0}",
ex.Message));
}
}
Interface:
public interface IPlugin
{
string _pluginName { get; }
string _pluginDetails { get; }
void PluginLaunched();
}
Plugin:
public class ListPlugins : IPlugin
{
public void PluginLaunched()
{
Controller _Controller = new Controller();
foreach (IPlugin plugin in PluginLoader.Plugins)
{
_Controller.WriteToRichTextBox(string.Format("{0}: {1}", plugin._pluginName, plugin._pluginDetails), _Controller.console);
}
}
public string _pluginName
{
get
{
return "listplugins";
}
}
public string _pluginDetails
{
get
{
return "This plugin shows all loaded plugins and what they do.";
}
}
}
You have already done the hard part of instantiating the plugin, now you just need to pass the controller when you execute the plugin like so:
plugin.PluginLaunched(controller);

Updating label with data from thread

I am trying to update a label in windows forms. The action is happening in a separate class but while the action is happening on a separate class. The label should be updated, but things seem to be not working. Kindly assist
Below is the Back code of the form ProcessingUI
public partial class ProcessingUI : Form
{
private void start_Click(object sender, EventArgs e)
{
StartProcessingTask();
}
private void StartProcessingTask()
{
if (_isRunning)
return;
_isRunning = true;
_taskToken = new CancellationTokenSource();
Task.Factory.StartNew(() =>
{
while (_isRunning)
{
var data = _processing.Processdata(lblCounter, _taskToken);
if (data.Success)
_isRunning = false;
if (_taskToken.IsCancellationRequested)
return;
}
});
}
public delegate void SetStatusCallback();
public void UpdateStatus()
{
lblCounter.Invoke((Action)delegate
{
lblCounter.Text += new EventHandler(_processing.Raise);
});
}
}
Then here is a separate class that has the action, basically its just updating.
Now on update I just want to pass the record that is being updated. So i call the Method from the form and use it in this class.
public class Processing
{
public Results Processdata(CancellationTokenSource taskToken)
{
foreach (var record in dataCases)
{
//Doing other things here like updating
new ProcessingUI().UpdateStatus();//This is the method I am calling from the form.
get(record.RequestReference);
}
}
public string get(string msg)
{
return msg;
}
public void Raise(object sender, EventArgs e)
{
get("hello");
}
}
Using Progress to handle cross-thread access
public class Processing
{
public Results ProcessData(IProgress<string> statusReporter, CancellationToken cancellationToken)
{
foreach (var record in dataCases)
{
// Doing other things here like updating
// Update the status:
statusReporter.OnReport(record.RequestReference);
// Stop if the task has been cancelled:
cancellationToken.ThrowIfCancellationRequested();
}
}
}
public partial class ProcessingUI : Form
{
private void start_Click(object sender, EventArgs e)
{
StartProcessingTask();
}
private void StartProcessingTask()
{
if (_isRunning)
return;
_isRunning = true;
_taskToken = new CancellationTokenSource();
CancellationToken cancellationToken = _taskToken.Token;
IProgress<string> statusReporter = new Progress<string>(UpdateStatus);
Task.Run(() =>
{
while (_isRunning)
{
var data = _processing.ProcessData(lblCounter, cancellationToken);
if (data.Success)
{
_isRunning = false;
}
else
{
cancellationToken.ThrowIfCancellationRequested();
}
}
});
}
private void UpdateStatus(string message)
{
lblCounter.Text = message;
}
}

Windows service error: the savedState dictionary does not contain the expected values and might have been corrupted

I'm trying to create multiple services using one EXE file.
I've added a installer class:
[RunInstaller(true)]
public partial class POCInstall : System.Configuration.Install.Installer
{
private ServiceProcessInstaller m_ServiceProcess;
private ServiceInstaller m_ServiceInstaller;
public POCInstall()
{
InitializeComponent();
m_ServiceProcess = new ServiceProcessInstaller();
m_ServiceProcess.Account = ServiceAccount.NetworkService;
m_ServiceProcess.Username = null;
m_ServiceProcess.Password = null;
m_ServiceInstaller = new ServiceInstaller();
m_ServiceInstaller.BeforeInstall += new InstallEventHandler(onBeforeInstall);
m_ServiceInstaller.BeforeUninstall += new InstallEventHandler(onBeforeUninstall);
m_ServiceInstaller.BeforeRollback += new InstallEventHandler(onBeforRollback);
m_ServiceInstaller.ServiceName = "POCService";
this.Installers.Add(m_ServiceProcess);
this.Installers.Add(m_ServiceInstaller);
}
private void onBeforRollback(object sender, InstallEventArgs e)
{
string serviceName = ConfigurationManager.AppSettings["ServiceName"];
string serviceDsiaply = ConfigurationManager.AppSettings["ServiceDsiaply"];
m_ServiceInstaller.ServiceName = serviceName;
m_ServiceInstaller.DisplayName = serviceDsiaply;
}
private void onBeforeUninstall(object sender, InstallEventArgs e)
{
string serviceName = ConfigurationManager.AppSettings["ServiceName"];
string serviceDsiaply = ConfigurationManager.AppSettings["ServiceDsiaply"];
m_ServiceInstaller.ServiceName = serviceName;
m_ServiceInstaller.DisplayName = serviceDsiaply;
}
private void onBeforeInstall(object sender, InstallEventArgs e)
{
string serviceName = ConfigurationManager.AppSettings["ServiceName"];
string serviceDsiaply = ConfigurationManager.AppSettings["ServiceDsiaply"];
m_ServiceInstaller.ServiceName = serviceName;
m_ServiceInstaller.DisplayName = serviceDsiaply;
}
}
As you can see, I get the service name and parameter from the app config file:
<add key="ServiceName" value="POCService1"/>
<add key="ServiceDsiaply" value="POC Service 1"/>
The service class is empty and only have empty onStart and OnStop methods.
public partial class POCService : ServiceBase
{
public POCService()
{
this.ServiceName = "POCService";
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
When I do the install using command line, %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe ServicePOC.exe
I get the error:
An exception occurred during the Rollback phase of the System.ServiceProcess.ServiceInstaller installer.
System.ArgumentException: The savedState dictionary does not contain the expected values and might have been corrupted.
Implement an empty public override void Commit(IDictionary savedState) method.

Confusion with attaching/detaching and different ObjectContext object

I open a new MessagesWindow which has this code:
namespace Newsletter.UI
{
public partial class MessagesWindow : Window
{
MessageService msgService;
public MessagesWindow()
{
InitializeComponent();
msgService = new MessageService();
}
private void CreateButtonClick(object sender, RoutedEventArgs e)
{
var createMessageWindow = new CreateMessageWindow { Owner = this };
createMessageWindow.ShowDialog();
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
private void messagesWindow_Loaded(object sender, RoutedEventArgs e)
{
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
private void EditButtonClick(object sender, RoutedEventArgs e)
{
if (gridMessages.SelectedItem == null)
MessageBox.Show("You have to choose the message first.");
else
{
var selectedMessage = (Message)gridMessages.SelectedItem;
var editMessageWindow = new EditMessageWindow(selectedMessage);
editMessageWindow.Owner = this;
editMessageWindow.ShowDialog();
}
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
}
}
I open a new window with EditButtonClick where I want to edit my Message. The code of the EditMessageWindow:
namespace Newsletter.UI
{
public partial class EditMessageWindow : Window
{
private Message editMessage;
private MessageService messageService;
public EditMessageWindow(Message message)
{
InitializeComponent();
editMessage = message;
messageService = new MessageService();
}
private void CreateMessageWindowLoaded(object sender, RoutedEventArgs e)
{
subject.Text = editMessage.Subject;
messageContent.AppendText(editMessage.Content);
senderComboBox.ItemsSource = messageService.GetAllSenders();
mailingListComboBox.ItemsSource = messageService.GetAllMailingLists();
}
private void SaveClick(object sender, RoutedEventArgs e)
{
editMessage.Date = DateTime.Now;
editMessage.Content = messageContent.Text;
editMessage.MailingList.Add(messageService.GetAllMailingLists()[mailingListComboBox.SelectedIndex]); //ERROR
editMessage.Sender = messageService.GetAllSenders()[senderComboBox.SelectedIndex];
editMessage.Subject = subject.Text;
editMessage.HasAttachments = false;
messageService.EditMessage(editMessage);
Close();
}
}
}
I get an error on SaveClick:
The relationship between the two objects cannot be defined because
they are attached to different ObjectContext objects.
Finally, MessageService code:
namespace Newsletter.Services
{
public class MessageService
{
private NewsletterEntities _context;
public MessageService()
{
_context = new NewsletterEntities();
}
public void AddMessage(Message newMessage)
{
_context.Messages.AddObject(newMessage);
_context.SaveChanges();
}
public void EditMessage(Message editMessage)
{
var messageToChange = (from m in _context.Messages where editMessage.MessageID == m.MessageID select m).FirstOrDefault();
if (messageToChange != null)
{
messageToChange = editMessage;
_context.SaveChanges();
}
}
public List<Message> GetAllMessages()
{
return (from m in _context.Messages select m).ToList();
}
public List<MailingList> GetAllMailingLists()
{
var query = from m in _context.MailingLists select m;
return query.ToList();
}
public List<Sender> GetAllSenders()
{
var query = from m in _context.Senders select m;
return query.ToList();
}
public void DeleteMessage(Message message)
{
List<MailingList> mailingLists = new List<MailingList>();
foreach(MailingList ml in message.MailingList.ToList())
{
ml.Message.Remove(message);
}
_context.Messages.DeleteObject(message);
_context.SaveChanges();
}
}
}
I'm getting consfused with all those layers and contexts. I know I should probably somehow detach the message, do something with it and attach but I don't know where and how. Should I do it in the service layer in MessageService, UI layer, or maybe DAL layer where I have all my entities? Or should I redesign my solution and do the context logic in different place?
you appear to have the setup of context per window. that will have 2 impacts on how you maintain the objects within the context.
You do not want to pass objects from form to form. instead you will pass the ID(s) from form to form and load the entity within the context.
As an entity is updated within one context you will need to notify the other windows/contexts of the change so they can refresh their data.
here is an MSDN article detailing the process of context per form. The article uses NHibernate, but the process would be almost identical for EF and DbCotext
http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

Categories

Resources