Why does my database not open? - windows-phone-8.1

I am using SQLite in a windows 8.1 mobile app and when I am trying to delete something from the database I get an exception in the method RunInTransaction:
Cannot create commands from unopened database.
But when I try to insert something it works fine!
This is the insertion method:
// Inserts a new place in the Places table.
public void InsertPlace(PlacesTable place) {
using (var dbConn = new SQLiteConnection(App.DB_PATH)) {
dbConn.RunInTransaction(() => {
dbConn.Insert(place);
});
}
}
And this is the delete method:
// Deletes all the places from the database.
public void DeletePlaces() {
using (var dbConn = new SQLiteConnection(App.DB_PATH)) {
dbConn.RunInTransaction(() => {
dbConn.DropTable<PlacesTable>();
dbConn.CreateTable<PlacesTable>();
dbConn.Dispose();
dbConn.Close();
});
}
}
Why does this exception occur in the second case?
So, I found out that Dispose and Close were responsible for the exception, though I would like someone to explain me why this happened.
Was Close causing a problem because I had using (var dbConn = new SQLiteConnection(App.DB_PATH)) and Dispose for a similar reason?
I had found this at a tutorial, so it took me some time until I thought that the code had a mistake.

Related

EF6 - There is already an open DataReader associated with this Command which must be closed first

I am coding a MVC5 internet application and am using EF6.
I have an Edit ActionResult that is called when an Asset object is edited. I also need to update other objects values when an Asset object is edited. The UpdateAssociatedAssetObjects function does this.
I am getting the following error:
There is already an open DataReader associated with this Command which must be closed first.
In the UpdateAssociatedAssetObjects function, at the following line of code:
if (item.mapMarker.Id == asset.Id)
Here is the Edit ActionResult:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(AssetViewModel assetViewModel)
{
if (ModelState.IsValid)
{
db.Entry(assetViewModel.asset).State = EntityState.Modified;
assetViewModel.asset.lastUpdate = DateTime.Now;
if (assetViewModel.asset.linkFromExternalResource)
{
assetViewModel.asset.webAddress = assetViewModel.webAddress;
}
else
{
assetViewModel.asset.webAddress = assetViewModel.filename;
}
db.Entry(assetViewModel.asset).Property(uco => uco.creationDate).IsModified = false;
db.Entry(assetViewModel.asset).Property(uco => uco.userName).IsModified = false;
assetService.UpdateAssociatedAssetObjects(db, assetViewModel.asset);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(assetViewModel);
}
Here is the UpdateAssociatedAssetObjects function:
public void UpdateAssociatedAssetObjects(CanFindLocationDatabaseContext db, Asset asset)
{
foreach (var item in db.mapLocations)
{
if (item.mapMarker.Id == asset.Id)
{
item.lastUpdate = DateTime.Now;
}
}
}
Can I please have some help with this code?
I have tried placing the UpdateAssociatedAssetObjects function after the await db.SaveChangesAsync() and using a new database context object, but the error still occurs.
Thanks in advance
In your controller method you are already opening a db connection to an entry of asset.
In your method UpdateAssociatedAssetObjects you're trying to open a second db connection reading, while you're main is still open. Get the first object or get the list in the second object.
An alternate solution is to update the db twice.

Wait until async operation ends Windows Phone

I am trying to parse some pois from a xml download from a server and I saw that it is done after the program continues in the main thread. I haven't found a way to solve it because I need it.
using System.Threading;
namespace XML_Parser
{
class XMLParserPOI_Wiki
{
private static XMLParserPOI_Wiki objSingle = new XMLParserPOI_Wiki();
public static XMLParserPOI_Wiki ObjSingle
{
get { return objSingle; }
set { objSingle = value; }
}
private List<POI> places;
public List<POI> Places
{
get { return places; }
}
private XMLParserPOI_Wiki()
{
}
public void parseWikitude(string url)
{
places = new List<POI>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
XNamespace ns = "http://www.opengis.net/kml/2.2";
XNamespace ns2 = "http://www.openarml.org/wikitude/1.0";
var placemarkers = xdoc.Root.Descendants(ns + "Placemark");
places =
(from query in xdoc.Root.Descendants(ns + "Placemark")
select new POI
(
...
)).ToList();
System.Diagnostics.Debug.WriteLine("Lista");
System.Diagnostics.Debug.WriteLine(places.Count);
}
}
}
}
In my main class:
XMLParserPOI_Wiki parserXML = XMLParserPOI_Wiki.ObjSingle;
parserXML.parseWikitude("http://myurl.php");
System.Diagnostics.Debug.WriteLine("Lista de pois");
System.Diagnostics.Debug.WriteLine(parserXML.Places.Count);
for (int i = 0; i < parserXML.Places.Count; i++)
{
System.Diagnostics.Debug.WriteLine(parserXML.Places[i].getName());
}
It prints Lista de POis and 0, before Lista and X (number of pois)
I guess I should freeze main thread but I tried a couple of times with some examples and they didn't work.
Can you point me to any tutorial about this? More than get an answer I want to understand how to deal with this kind of operations
First of all, you don't want to block (freeze) the UI thread EVER!
This is called asynchronous programming. There are two things you can do to solve your problem (I recommend option 2!):
Use the classic callback model. You basically call some long operation on a background thread and give a function to it, to execute when the long operation is done. Here's how to do it in your case.
At the end of the HttpsCompleted method, invoke what you need on the UI Thread using:
Deployment.Current.Dispatcher.BeginInvoke(delegate() {
//The code here will be invoked on the UI thread
});
If you want to make the parseWikitude method reusable, you should pass an Action to it. This way you can call it from multiple places and tell it what to do on the UI thread when the parsing is done. Something like this:
public void parseWikitude(string url, Action callback) {
places = new List<POI>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url), callback);
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
...
var callback = (Action)e.UserState;
Deployment.Current.Dispatcher.BeginInvoke(callback);
}
}
//And then when you use it, you do it like that
parserXML.parseWikitude("http://myurl.php", delegate() {
//The code here will be executed on the UI thread, after the parsing is done
});
Use the (rather) new asnyc pattern in .NET. You should read about this, as it is one of the best features of .NET if you ask me. :) It basically does the callback thing automatically and makes the code a lot easier to read/maintain/work-with. Once you get used to it, that is.
Here's an example:
public Task<List<POI>> parseWikitude(string url) {
TaskCompletionSource<List<POI>> resultTaskSource = new TaskCompletionSource<List<POI>>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url), resultTaskSource);
return resultTaskSource.Task;
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
//If needed, run the code here in a background thread
//...
var resultTaskSource = (TaskCompletionSource<List<POI>>)e.UserState;
resultTaskSource.SetResult(places);
}
}
//And when you need to use it, do it like that (note, this must be invoked in an async method!)
var places = await parser.parseWikitude("http://myurl.php");
//The code here will be executed on the same thread when the parsing is done, but the thread will not be blocked while the download is happening.
So, these are the two ways you can handle it. Option one is old-school, classic and easy. Option two is the new and cool way of doing async stuff. It really is a must-know. Simplifies a lot of things once you get used to it.
P.S. Sorry if I got carried away. :D

Query String Not Getting Set - Cimbalino Windows Phone

I am using Cimbalino navigation but the query param never gets set for me.
Main View Model
private readonly INavigationService navigationService = null;
public MainViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
NavigateToPg2Cmd = new RelayCommand(() => NaviagateToPg2());
NavigateToPg2WithParmsCmd = new RelayCommand(() => NaviagateToPg2WithParms());
}
private void NaviagateToPg2WithParms()
{
navigationService.NavigateTo(new Uri("/Views/SecondPg.xaml?parameter=1&parm2=2", UriKind.Relative));
}
When I look into NavigationService the Query Param dictionary is always 0.
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
}
else
{
}
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SecondVM>();
}
Edit
Ok, I figured it out. When NavigateTo runs it still has not split the query string out yet so that's why it is zero.
I was also trying to do
private readonly INavigationService navigationService = null;
public SecondVM(INavigationService navigationService)
{
this.navigationService = navigationService;
if (IsInDesignMode)
{
Message = "Design Mode";
}
else
{
if (navigationService.QueryString.ContainsKey("paramter"))
{
Message = navigationService.QueryString["parameter"];
}
}
}
what did not work either as I guess it was too early as well. I really would like to pull it out at constructor time though, is there a way to do this?
I know it's not 100% the solution you are looking for, but you are true... You'll need to wait until the view is loaded before accessing the QueryString params in the ViewModel!
To do this, hook into the Loaded event of the view and pass it to a Command on the viewmodel!
If created a demo of this on my github to get you started: https://github.com/Depechie/NavigationParams

ASP.NET MVC LINQ-2-SQL as model - how to update?

Is it possible to use LINQ2SQL as MVC model and bind? - Since L2S "attachement" problems are really showstopping.
[HttpPost]
public ActionResult Save(ItemCart edCart)
{
using (DataContext DB = new DataContext())
{
DB.Carts.Attach(edCart);
DB.Carts.Context.Refresh(RefreshMode.KeepChanges, edCart);
DB.Carts.Context.SubmitChanges();
DB.SubmitChanges();
}
return RedirectToAction("Index");
}
That does not work. :S
What does your Save View look like?
You can't just attach a new item to the EntitySet like that. -> Attaching requires a lot of checks and it is a real pain to implement. I tried it myself and didn't like it at all.
In your [HttpPost] method you'll need to update the model before you can save it:
[HttpPost]
public ActionResult Save(int id, ItemCart edCart) {
DataContext DB = new DataContext(); // I'm doing this without a using keyword for cleanliness
var originalCart = DB.Carts.SingleOrDefault(c => c.ID == id); // First you need to get the old database entry
if (ModelState.IsValid & TryUpdateModel(edCart, "Cart")) { // This is where the magic happens.
// Save New Instance
DB.SubmitChanges.
return RedirectToAction("Details", new { id = originalCart.ID });
} else {
// Invalid - redisplay with errors
return View(edCart);
}
}
It tries to update the model from the controllers valueprovider using they "Cart" prefix.

Model binding issue in LINQ to SQL

I am just now starting to work with LINQ, and am pretty familiar with MVC. I have a strongly typed view that is updating a record. I have successfully done a creation:
This works fine, and creates a record in the database:
public ActionResult Create(TABLEMODEL tableModel)
{
DBDataContext db = new DBDataContext();
if (ModelState.IsValid)
{
db.TABLEMODEL.InsertOnSubmit(tableModel);
db.SubmitChanges();
}
}
But when trying to update:
public ActionResult Manage(TABLEMODEL tableModel)
{
DBDataContext db = new DBDataContext();
if (ModelState.IsValid)
{
db.SubmitChanges();
}
}
This fails, in the sense that it does not update the record in the database. No actual error/exception occurs, and I can step through it just fine.
I am sure I am missing something, but cannot find what. I appreciate any help on this matter.
UPDATE
I did notice that if I get a record using the DataContext:
DBDataContext db = new DBDataContext();
var m = db.TABLEMODELs.Single(m => m.ID == 1);
m.Name = "UpdatedName";
db.SubmitChanges();
This does update, so I assume I am somehow not binding from my model to the LINQ context.
My Solution
I found that you need to retrieve the object and then update that with the form. Simple enough.
[HttpPost]
public ActionResult Manage(int ID, FormCollection form)
{
DBSDataContext db = new DBSDataContext();
var t= db.TABLEMODELs.Single(b => b.ID == ID);
UpdateModel(t);
if (ModelState.IsValid)
{
db.SubmitChanges();
}
return View(t);
}
You should re-query the original tableModel, map the updated row and then update.
Perhaps something like this (example only, not knowing anything about your schema):
var originalTableModel = db.GetById( tableModel.Id);
originalTableModel.FirstName = tableModel.FirstName;
db.SubmitChanges();