SQLite no longer seems to work on xamarin android - xamarin.forms

We have a Xamarin.Forms project that needed to use the sqlite local db to store date. EF Core's sqlite library was used to set this up and by different developers from different PCs (vs 2019). Initially, it was used with the Database.EnsureCreated() function and later with ef core's migrations. All went smooth for more than a month.
Last week all of a sudden the android app wouldn't start on any one's PC due to some error with sqlite. It showed the following error:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
I spent a while trying all kinds of fixes and rollbacks thinking it was an issue with the code. This included the following:
Deleted obj and bin folders, cleaned and rebuilt for all below steps.
Downgraded the version of ef to 2.2.3 (the version we started with)
Rolled back to git commits up to a week back
Upgraded the versions of dependencies of ef core
Removed the past few migrations
Downgraded xamarin forms to 3.6.x
After trying the above and several other fixes, finally upgrading the versions of java and android SDK worked last Friday (on all PCs). Once this fix worked everything went smooth that day. On Tuesday once again the issue was back (no library updates or code changes). A deeper look at EF Cores logging shows that it crashes the moment it attempts to connect to a db.
The issue can be replicated on the android devices but not the emulators. I am not sure if there is some new permission in android we need to request for.
I finally created a new xamarin forms project with sqlite setup. I used the pcl library and ef core. I still found the same error.
Here is the git hub that replicates the issue https://github.com/neville-nazerane/xamarin-site
Update
Just something i noticed. eariler my database file was named "main.db". Now no matter what i change this file name to or no matter what variables i change. it always shows database name as "main" in logs. Not sure if changing the db name would fix the issue. However, never found a way to change this db name. I tried different connection strings, it just said "database" and "db" were unknown keys
Update
Steps to replicate:
using (var db = new AppDbContext())
{
db.Add(new Person {
Age = 55,
Name = "Neville"
});
db.SaveChanges();
Person[] alldata = db.People.ToArray();
}
The definitions of Person and AppDbContext are quite obvious. So, with the spirit of not making the question too long, I am not posting it here. However, if required I can post them too.

This is a bug with the Xamarin.Forms and Mono.
It was detected since a couple of months ago, it was fixed but then there was some regression (with VS 2019 v16.1).
Even with the latest release (v16.1.2) the bug still happens, so we need to wait for a fix.
Sources:
https://github.com/mono/mono/issues/14170
https://github.com/xamarin/xamarin-android/issues/3112
https://github.com/xamarin/xamarin-android/issues/2920

Due to slight differences of the particular file systems on the native side, I would suggest creating an interface to handle the actual database file handling on the native application level.
So here is how I implemented SQLite using the nuget package SQLite.Net-PCL:
In the shared project, create a new interface, for instance FileHandler.cs
public interface IFileHandler
{
SQLite.SQLiteConnection GetDbConnection();
}
You may want to extend that with more methods to save or retrieve various files, but for now we will just have the GetDbConnection Method to retrieve a working SQLite Connection.
Now in your Android implementation, we add the native implementation to that interface:
Create a new class called FileHandler.cs in your android project:
[assembly: Dependency(typeof(FileHandler))]
namespace YourProjectName.Droid
{
public class FileHandler : IFileHandler
{
public SQLite.SQLiteConnection GetDbConnection()
{
string sqliteFilename = "YourDbName.db3";
string path = Path.Combine(GetPersonalPath(), sqliteFilename);
SQLiteConnectionString connStr = new SQLiteConnectionString(path, true);
SQLiteConnectionWithLock connection = new SQLiteConnectionWithLock(connStr, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.NoMutex);
return connection;
}
private string GetPersonalPath()
{
return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
}
}
}
Now back again in your shared code you can access that connection with the following code:
using (SQLiteConnection connection = DependencyService.Get<IFileHandler>().GetDbConnection())
{
// Do whatever you want to do with the database connection
}

Alright mate, I don't understand what issue you are facing. It might be an issue with your machine, I'd suggest using another computer/laptop.
I took the exact code that you shared on the Github. I was able to build it on my Mac computer in VS 2019 and installed the application in debug mode on my phone. I was able to add a date successfully, as you can see in the picture, and I placed an Exception Catchpoint and faced no exceptions.
I then proceeded to add another entry with the same details and it errored out with the message that you can see here
I would also suggest using Xamarin Profiler or any other Android logger to see the Stack Trace that you aren't able to see in your application output. It will give you details of the error, that you can share here for us to understand better.

Related

Upgrading Wicket 9.0.0 to 9.3.0: runtime error when try to access database

I am attempting to upgrade from Wicket 9.0.0 to Wicket 9.3.0. When I change the version in a quick-start application, everything is fine.
The problem occurs in my real application, where we were originally using Jakarta Enterprise Beans 8.0.0. At runtime, when a database access was attempted, we got an exception with the following message:
Last cause: net.sf.cglib.proxy.MethodInterceptor not found by org.objectweb.asm [23]
Trying to use Jakarta EE 9.1 instead
I changed my pom.xml as follows:
<jakartaee>9.1.0</jakartaee>
<wicket.version>9.3.0</wicket.version>
I downloaded the jar for Jakarta EE 9.1, changed "javax" to "jakarta" throughout my application, rebuilt it and tried to run again.
The result was still not perfect, but significantly better than before: a plain old null pointer exception instead of any weird errors about cglib.
Here's the section of code that now causes the trouble:
#EJB(name = "AdminNotesFacade")
private AdminNotesFacade adminNotesFacade;
public AdminNotesFacade getAdminNotesFacade() {
return adminNotesFacade; //ACTUALLY RETURNS NULL
}
So now the big question is: what do I need to do/change to make the #EJB work instead of returning null?
Checking the Payara log, I get this error:
java.lang.RuntimeException: Unable to load the EJB module. DeploymentContext does not contain any EJB. Check the archive to ensure correct packaging for D:\Dev\icase2\target\icase2.
If you use EJB component annotations to define the EJB, and an ejb or web deployment descriptor is also used, please make sure that the deployment descriptor references a Java EE 5 or higher version schema, and that the metadata-complete attribute is not set to true, so the component annotations can be processed as expected
at org.glassfish.ejb.startup.EjbDeployer.prepare(EjbDeployer.java:189)
Adding further details, 2022-05-06
I wonder if we were going off on the wrong track when we thought that we could fix this by upgrading our jakartaee version. From Wicket 9.0 to 9.3 is only a change of minor version and you wouldn't expect to have to make such fundamental changes to get a minor upgrade working.
I've tried using Wicket 9.9.1 instead, in case this problem has been fixed in more recent versions, but it's exactly the same.
Anyway, I have created a very small "quick-start" application, based on Wicket's own templates, to reproduce the problem. I have stuck with the original "javax" version, and added just one EJB - a JavaMail bean. I think it's probably interesting to know that it's not a specifically database-related issue. We just can't seem to load any EJBs at all.
In the Wicket 9.0.0 version, a simple form is displayed on the home page, allowing the user to enter their email address. When they submit the form, a test message is sent to that address. It works fine.
Then if I change the Wicket version to 9.3.0 but make no other changes at all, it doesn't even get to the stage of displaying the home page, it immediately crashes with the message "Last cause: net.sf.cglib.proxy.MethodInterceptor not found by org.objectweb.asm [23]"
For what it's worth, here's the code that triggers the error.
public class HomePage extends WebPage {
#EJB(name = "EmailerFacade")
private EmailerFacade emailerFacade;
private static final long serialVersionUID = 1L;
private String sendTo = "";
public HomePage(final PageParameters parameters) {
super(parameters);
add(new Label("version", getApplication()
.getFrameworkSettings().getVersion()));
FeedbackPanel feedback = new FeedbackPanel("feedback");
add(feedback);
final Form emailForm = new Form("emailForm") {
#Override
protected void onSubmit() {
emailerFacade.sendMessage(sendTo, "Test message from quick-start",
"Version is " + getApplication().getFrameworkSettings()
.getVersion());
info("Tried to send message to " + sendTo);
}
};
add(emailForm);
final TextField<String> emailAddress = new TextField<>("emailAddress",
new PropertyModel<>(this, "sendTo"));
emailAddress.setLabel(Model.of("Email address"));
emailAddress.setRequired(true);
emailForm.add(emailAddress);
}
}
Wicket 9.x is based on javax.servlet APIs. To deploy it on jakarta.servlet supporting web container you will need to migrate the bytecode with a tool like https://github.com/apache/tomcat-jakartaee-migration.
I am not sure whether Payara does something smart at runtime to support both javax.** and jakarta.** classes.
Tomcat 10.x supports migration of the classes at application start time by deploying your app in the special $CATALINA_HOME/webapps-javaee folder.
This answer was actually provided by Sven Meier. He commented:
Use the new system property to switch to ByteBuddy in Wicket 9.x:
-Dwicket.ioc.useByteBuddy=true
To expand a bit on this, I found I needed to do three things:
Set the system property "wicket.ioc.useByteBuddy" to true as specified by Sven
Add a dependency on byte buddy
Upgrade to a higher version than I was initially attempting to do: 9.3.0 was not good enough. I see in a comment above by Sven, he says that the migration to byte buddy was actually done in 9.5. So in fact I upgraded to the latest version, which is currently 9.9.1.
Here is the dependency on byte buddy that I added:
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.12.10</version>
</dependency>

Unable to open SQLite database file from local data store of UWP app

I'm using this section of this official MSDN tutorial: Use a SQLite database in a UWP app but I'm getting the following error:
REMARK: There are many online posts related (or similar) to this issue but none seems to have a solution. Most of these posts are a few years old so I thought this issue would have been resolved by now. Moreover, the above mentioned tutorial is using .NET Standard Class library project, as well. And the online posts regarding the issue do not have .NET Standard involved. So, I was wondering if the issue is caused by the use of .NET Standard library. Regardless, a solution will be greatly appreciated.
SQLite Error 14: 'unable to open database file'
Error occurs at line db.Open() of this code:
public static void InitializeDatabase()
{
using (SqliteConnection db =
new SqliteConnection("Filename=sqliteSample.db"))
{
db.Open();
String tableCommand = "CREATE TABLE IF NOT " +
"EXISTS MyTable (Primary_Key INTEGER PRIMARY KEY, " +
"Text_Entry NVARCHAR(2048) NULL)";
SqliteCommand createTable = new SqliteCommand(tableCommand, db);
createTable.ExecuteReader();
}
}
NOTES:
The line just below the above code reads: This code creates the SQLite database and stores it in the application's local data store. That means the app should have access to that local data store.
I'm using latest version 16.3.5 of VS2019 on Windows 10. The target version on the project is selected as Windows 10 1903 and min version as Windows 10 1903
UPDATE
This similar official 3 years old sample works fine. So, the problem seems to be related to newer versions of .NET Core. But I need to use latest version of .NET Core for other features my app is using that are not available in the older versions.
I also tried this similar old tutorial, but it did not on new version of .NET Core work either - giving exact same error.
The old problem reported in 2016 here to Microsoft seems to have resurfaced again with the new version of .NET Core.
This is a misunderstanding, SqliteConnection db = new SqliteConnection("Filename=sqliteSample.db") can not create a Sqlite file, but access the existing Sqlite database file through the path.
So you need to create a valid sqliteSample.db file and place it in the root directory of the UWP project. Select the content in the Properties -> Build operation to ensure it will be loaded into the application directory.
Update
Please create the sqliteSample.db file in LocalFolder first.
await ApplicationData.Current.LocalFolder.CreateFileAsync("sqliteSample.db", CreationCollisionOption.OpenIfExists);
Then use the path to access the database file
string path = Path.Combine(ApplicationData.Current.LocalFolder.Path, "sqliteSample.db");
using (SqliteConnection db =
new SqliteConnection($"Filename={path}"))
{
// ...
}
Best regards.

Xamarin.Auth AccountStore - KeyStore was not initialized

I've had this Xamarin.Auth AccountStore working in my app for a while, but then decided to do some updates to some Nuget Packages and Target Android versions >_<
I now have no idea what went wrong and how to get it working again, here is the exception:
Java.Security.KeyStoreException: KeyStore was not initialized
The code is pretty simple and looks like this:
var accountStore = AccountStore.Create(Android.App.Application.Context);
var accounts = accountStore.FindAccountsForService(providerName);
The 2nd line is throwing the exception.
This is in the Android project, being called from a PCL DependencyService.
It has been working this way for a while, I guess something changed in a version update in one of the packages but I don't know what, any ideas?
try to repair your visual studio installation.
This made the trick for our project. We had the same problems like you.

How to properly update SQL database in Azure after EF Code First model of asp.net mvc model change?

It seems like I always have a variety of problems doing this, and usually I end up nuking the db out of frustration and rebuilding, but obviously there has to be some way to do this.
I have an existing asp.net mvc web app living with its sql db in azure. Works fine has some data that can be replaced but, again, the point is to learn how to update model without destroying the database.
In VS2017 I add one property public string ScreenShot { get; set; }
I make some small changes to my mvc and web api controllers to handle this extra property. I update my localdb via packmanager console and add-migration addprop and update-database. Works fine, run it locally, no probs.
Goto publish, goto settings, check update database. Click publish.
It hangs for like 5 or 6 min and I get:
Warning : A project which specifies SQL Server 2016 as the target platform may experience compatibility issues with Microsoft Azure SQL Database v12. when publishing
I try publishing several times and get the same thing. Google, look around, scratch my head, try again and it seems to publish. Site opens, and somehow I have lost my bootstrap theme. In fact in my Content folder I now have 4 files i believe are new: bootstrap-theme. (css,css.map, min.css, min.css.map) (same prefix , different suffix) as well as what I think are virgin versions of those without theme in the name, and seems to be the default mvc theme of black and white.
When I goto my app and I get an generic error and checking elmah I get:
System.InvalidOperationException: The model backing the 'TaskTrackerContext'
context has changed since the database was created. Consider using Code
First Migrations to update the database (http://go.microsoft.com/fwlink/?
LinkId=238269).
Well I really thought thats what I did. Almost forgot one thing! Maybe this is where my problem lies: I actually had to run two migrations-in addition to the model change I dropped a column that had never been used (scaffolding a controller for a DTO version of one of my models added it to my context which created a table).
I did create a new branch before making any of these change so I could just revert back but at some point I have to make this work and have to understand how to do it without destroying my db and remaking fresh.
A check in SQL object explorer shows it added the ScreenShot column to my table but didn't remove the unused table.
This works for me :
In visual Studio, go to publish settings and then select the option
Execute Code First Migration
Please see the screenshots below
Kind regards

Mono.Data.Sqlite.SqliteConnection requiring a version of 'System' that doesn't make sense

We're having issues with our Sqlite PCL Project.
The issues
1) Anywhere that references Mono.Data.Sqlite.SqliteConnection shows the following error.
Module 'System, Version 4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' should be referenced.
2) Anything trying to use File.Exists is showing a compiler error
Cannot resolve symbol 'File'
The particulars
We're using .NET Portable Subset 158
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile158\
We've included
Mono.Data.Sqlite
C:\Program Files (x86)\Mono-3.2.3\lib\mono\4.5\Mono.Data.Sqlite.dll
System.Data
C:\Program Files (x86)\Mono-3.2.3\lib\mono\4.5\System.Data.dll
I have no idea where to go from here.
Here's a class file containing the issues with SqliteConnection
using System;
using Mono.Data.Sqlite;
namespace OurApplication.AppCore.Data.Sqlite
{
public class DbConnectionProvider : IDbConnectionProvider
{
private readonly string _connectionString;
public DbConnectionProvider(string sqliteDatabasePath, string databaseName)
{
// the sqliteDatabasePath is hard coded in 'Data.Sqlite.DbProvider'
// _sqliteDatabasePath = "{0}.sqlite3";
_connectionString = string.Format("Data Source=" + sqliteDatabasePath, databaseName);
}
public SqliteConnection GetOpenConnection()
{
var connection = new SqliteConnection(_connectionString);
if (connection == null) throw new Exception("Could not create a database connection.");
connection.Open();
return connection;
}
}
}
Gist with more code examples
If this approach isn't feasible, I'm open to other alternatives. I'm looking into Sqlite.Net but the API doesn't really do what I want with regards to a custom DbReader and such.
I'm also interested in Stuart Lodge's MvvmCross Sqlite stuff, but really have no idea how to integrate the platform specific goodness. Honestly, I can't even figure out how to Execute Parameterized Queries.
I think my preference would be to use MvvmCross-SQLite if I can just get it figured out.
For references, this is how our Solution is structured.
OurApplication.App.Droid
OurApplication.AppCore
OurApplication.AppCore.Data.Sqlite (This is the project I'm working in.)
OurApplication.AppCore.Data.SqlServer
For non-portable APIs MvvmCross generally provides interfaces within PCLs with platform specific implementations on each platform.
The pattern used is called "plugins" - but really these are just a simple layer on top of an IoC container. You can see more about this on:
N=31 video in the tutorials - http://mvvmcross.wordpress.com - http://slodge.blogspot.co.uk/2013/06/n31-injection-platform-specific.html
the wiki - https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins
For File.Exists, MvvmCross provides an IMvxFileStore api - see https://github.com/MvvmCross/MvvmCross/blob/v3/Plugins/Cirrious/File/Cirrious.MvvmCross.Plugins.File/IMvxFileStore.cs
For SQLite MvvmCross has wrapped the SQLite-net library.
The original attempt to do this is in https://github.com/MvvmCross/MvvmCross/tree/v3/Plugins/Cirrious/Sqlite and is based off an early 2012 version of SQLite-net. A video intro to this is available in N-10 in http://mvvmcross.wordpress.com. This project has now been marked as obsolete simply because I don't plan to do any updates to it.
The newer attempt at portable SQLite-net has been put in its own repo to allow more people to contribute to it without confusing the main MvvmCross repo. It is in https://github.com/MvvmCross/MvvmCross-Sqlite - it is based off the latest SQLite-net (late 2013) which was split into interface and non-interface parts by #jarroda. The same N-10 video intro from http://mvvmcross.wordpress.com should work with this project too - just with a different namespace.
This source is currently live and builds fine here in my stable WinRT/WP7/Xamarin VS2012 environment. There will be changes in the coming weeks to address changes forced on MvvmCross by the latest Xamarin and Microsoft PCL changes. I'm afraid no-one can help with "spewing out errors" - that's not a techie term anyone can really help with.
There is at least one other PCL adaption of SQLite-net I've seen recently - but I can't find a link to that at present.

Resources