SQLite-net-pcl not working properly on Android 7.0 (Xamarin) - xamarin

SQLite-net-pcl seem's to work on all platforms except Android 7.0.
So far on Android 7.0 from a fresh install the application will crash due to an SQLException with the issue that it can't create a PK. If I uninstall the applications storage I.e. wipe the app from application settings, the app then works perfectly.
All other platforms seem to install instantly. See for youself https://play.google.com/store/apps/details?id=com.purewowstudio.fivestartips
I cannot seem to fix this. Worst of all, my iOS which shares a DB PCL doesn't load at all.
Does anyone know how to fix this?
Code example:-
Object
using System;
namespace App.LocalObjects
{
[Preserve(AllMembers = true)]
public class LocalArticle
{
[SQLite.PrimaryKey, SQLite.Column("articleObjectId")]
public string objectId { get; set; }
public DateTime createdAt { get; set; }
public DateTime updatedAt { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public int Status { get; set; }
public LocalArticle()
{
this.objectId = " ";
this.Title = " ";
this.Description = " ";
this.Url = " ";
}
}
}
Database
using System;
using System.Linq;
using System.Collections.Generic;
using SQLite;
using App.LocalObjects;
namespace App.DataLayer
{
public class Database
{
static object locker = new object();
public SQLiteConnection database;
public string path;
public Database(SQLiteConnection conn)
{
database = conn;
database.CreateTable<LocalArticle>();
}
public int SaveLocalArticleItem(LocalArticle item)
{
lock (locker)
{
LocalArticle article = database.Table<LocalArticle>().FirstOrDefault(x => x.objectId == item.objectId);
if (article != null && article.objectId.Equals(item.objectId) && !article.updatedAt.Equals(item.updatedAt))
{
database.Update(item);
return item.ID;
} else {
return database.Insert(item);
}
}
}
Code to initialize DB:
using System;
using System.IO;
using Android.App;
using App.BusinessLayer.Managers;
using App.BusinessLayer.ParseObjects;
using App.Utils;
using Android.Content;
using Com.Nostra13.Universalimageloader.Core;
using Com.Nostra13.Universalimageloader.Core.Assist;
using Android.Graphics;
using Com.Nostra13.Universalimageloader.Cache.Memory.Impl;
using Com.OneSignal;
using Parse;
using SQLite;
namespace App.Droid
{
[Application(LargeHeap = true)]
public class App : Application
{
public static App Current { get; private set; }
public ModelManager modelManager { get; set; }
private SQLiteConnection conn;
private ImageLoader imageLoader;
public App(IntPtr handle, global::Android.Runtime.JniHandleOwnership transfer)
: base(handle, transfer)
{
Current = this;
}
public override void OnCreate()
{
base.OnCreate();
SetupParse();
SetupDB();
}
private void SetupParse()
{
ParseObject.RegisterSubclass<ParseArticle>();
ParseClient.Initialize(new ParseClient.Configuration
{
ApplicationId = Constants.ParseApplicationID,
Server = Constants.ParseServer
});
}
private void SetupDB()
{
var sqliteFilename = Constants.DBName;
string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = System.IO.Path.Combine(libraryPath, sqliteFilename);
conn = new SQLiteConnection(path);
modelManager = new ModelManager(conn);
}
Here's what my project is currently referencing:-

Android N began actually enforcing rules around accessing the SQLite libraries that come with Android. Therefore any app (or app library) that was previously directly accessing SQLite without going through the special Java wrapper was already breaking the rules technically, the reason it was not a problem was because Android never really enforced those rules. Read more about that here
Now that Android N does enforce those rules, it causes the crash to occur. I am guessing that you are using the SQLite.Net-PCL library for accessing your SQLite DB. If you look here there is an open issue for that exact problem that the library creators never fixed.
We ran into the same issue and have since switched to the SQLite-Net-PCL library (notice the dash instead of the period) which works the exact same way and has an almost identical API. A link for that library can be found here.

i have same issue. i install this package for sqlite and set targeted version to android 8(oreo) my application works again

Related

Execute or compile runtime c# code on textbox after changes event - "PlatformNotSupportedException"

I am wondering to provide an option in my application to users to be able to customize buttons in ASP.NET CORE with Blazor.
I mean, C# code can be stored in database, and compiled/executed in runtime.
How can I "provide" an object from razor to be manipulated in this "code stored in the database" and after that, make those changes in runtime, after code been executed?
Please share your ideas.
I already tried some things, like this:
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.CSharp;using Newtonsoft.Json;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Projeto.Web.Pages.Components {
public class McwEditModel : CustomComponentBase
{
[Inject]
public IToastService ToastService { get; set; }
#region Parameters
[Parameter]
public string nome { get; set; }
#endregion
public void OnTextChanged(string newValue)
{
string source =
#"public class SomeClass {
public int OnTextChanged (string newValue) {
if (!string.IsNullOrEmpty(newValue)) {
ToastService.ShowWarning(newValue);
}
}
} ";
var compParms = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true
};
var csProvider = new CSharpCodeProvider();
CompilerResults compilerResults =
csProvider.CompileAssemblyFromSource(compParms, source);
object typeInstance =
compilerResults.CompiledAssembly.CreateInstance("SomeClass");
MethodInfo mi = typeInstance.GetType().GetMethod("OnTextChanged");
int methodOutput =
(int)mi.Invoke(typeInstance, new object[] { newValue });
InvokeAsync(StateHasChanged);
}
}}
The problem is that does not work, particularly I am getting the error "System.PlatformNotSupportedException: 'Operation is not supported on this platform.'" on line
" CompilerResults compilerResults = csProvider.CompileAssemblyFromSource(compParms, source); "
I am using Blazor .NET Core.
Is there any chance or way to achieve what I want?
I solved it using using Microsoft.CodeAnalysis package.
I needed to create a
public class Globals
{
[Inject]
public IToastService ToastService { get; set; }
public string newValue { get; set; }
public dynamic objeto { get; set; }
}
and inside my method I did:
public void OnTextChanged(string newValue){
Aql aql = new Aql { EaqcCodigo = "1", EaqcDescricao = "AQL" };
var globals = new Globals { ToastService = ToastService, newValue = newValue, objeto= aql };
CSharpScript.RunAsync("ToastService.ShowWarning(newValue + \"- desc:\" + objeto.EaqcDescricao + \"- cod:\" + objeto.EaqcCodigo);", ScriptOptions.Default.WithReferences("Microsoft.CSharp"), globals).Wait();
}
with this, now I can pass a dynamic object and also make any codes in a string field on database and retrieve this wherever I want, to customize a lot of things, ie: change of fields (in a custom generic and dynamic component)

ml.net model works with console application but not web api

I have created an MLModel with ml.net model builder and it works with a 'consume' console application and hard coded values for input. I wanted to go to the next step and feed values with web api. I am using a modified version of their tutorial example on using a mlmodel in a web api. When I use postman with the webapi I get the following error;
System.InvalidOperationException: 'Could not apply a map over type 'Single' to column 'PG' since it has type 'String''
The mlmodel builds successfully from model builder and the default code is generated from the model builder. Running a consume console app with hard coded values on the model works.
Here is the relevant code for modelinput
//*****************************************************************************************
//* *
//* This is an auto-generated file by Microsoft ML.NET CLI (Command-Line Interface) tool. *
//* *
//*****************************************************************************************
using Microsoft.ML.Data;
namespace JobClassMLModelML.Model.DataModels
{
public class ModelInput
{
[ColumnName("EducationLevel"), LoadColumn(0)]
public float EducationLevel { get; set; }
[ColumnName("Experience"), LoadColumn(1)]
public float Experience { get; set; }
[ColumnName("OrgImpact"), LoadColumn(2)]
public float OrgImpact { get; set; }
[ColumnName("ProblemSolving"), LoadColumn(3)]
public float ProblemSolving { get; set; }
[ColumnName("Supervision"), LoadColumn(4)]
public float Supervision { get; set; }
[ColumnName("ContactLevel"), LoadColumn(5)]
public float ContactLevel { get; set; }
[ColumnName("FinancialBudget"), LoadColumn(6)]
public float FinancialBudget { get; set; }
[ColumnName("PG"), LoadColumn(7)]
public string PG { get; set; }
}
}
And here it is for modeloutput
//*****************************************************************************************
//* *
//* This is an auto-generated file by Microsoft ML.NET CLI (Command-Line Interface) tool. *
//* *
//*****************************************************************************************
using System;
using Microsoft.ML.Data;
namespace JobClassMLModelML.Model.DataModels
{
public class ModelOutput
{
// ColumnName attribute is used to change the column name from
// its default value, which is the name of the field.
[ColumnName("PredictedLabel")]
public String Prediction { get; set; }
public float[] Score { get; set; }
}
}
I cloned the modelinput and modeloutput classes in equivalent webapi classes of jobclassdata and jobclassprediction respectively
The console application that works:
using System;
using Microsoft.ML;
using JobClassMLModelML;
using JobClassMLModelML.Model.DataModels;
namespace ConsumeApp
{
class Program
{
static void Main(string[] args)
{ // Load the model
MLContext mlContext = new MLContext();
ITransformer mlModel = mlContext.Model.Load("MLModel.zip", out
var modelInputSchema);
var predEngine =
mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
// Use the code below to add input data
var input = new ModelInput();
// input.
input.ContactLevel = 5;
input.EducationLevel = 5;
input.Experience = 5;
input.FinancialBudget = 5;
input.OrgImpact = 5;
input.ProblemSolving = 5;
input.Supervision =5;
//input.PG = "PG01";
// Try model on sample data
ModelOutput result = predEngine.Predict(input);
Console.WriteLine($"Predicted value: {result.Prediction} ");
}
}
}
Here is the code for the predict controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.ML;
using JobClassMLModelWebAPI.DataModels;
namespace JobClassMLModelWebAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PredictController : ControllerBase
{
private readonly PredictionEnginePool<JobClassData,
JobClassPrediction> _predictionEnginePool;
public PredictController(PredictionEnginePool<JobClassData,
JobClassPrediction> predictionEnginePool)
{
_predictionEnginePool = predictionEnginePool;
}
[HttpGet]
public JobClassData Get(JobClassData jobClassData)
{
return new JobClassData
{
// insert test data here
};
}
[HttpPost]
public ActionResult<string> Post([FromBody] JobClassData input)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
JobClassPrediction prediction =
_predictionEnginePool.Predict(input);
string PredictedJobGrade = prediction.Prediction;
return Ok(PredictedJobGrade);
}
}
}
Here is json body code posted
{
"educationLevel": 3,
"experience": 3,
"orgImpact": 3,
"problemSolving": 3,
"supervision": 3,
"contactLevel": 4,
"financialBudget": 4,
"pg" : "PG01"
}
The expected result would be predicted paygrade such as PG03. Instead the error is
System.InvalidOperationException: 'Could not apply a map over type 'Single' to column 'PG' since it has type 'String''
at the line
JobClassPrediction prediction =
_predictionEnginePool.Predict(input);
with no compile error and with console app working is the format of the json input?
Thanks

SQLite.Net Update generating error "it has no PK"

I'm using Lync syntax in a PCL using Xamarin.
public class settings
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string user_name { get; set; }
public string password { get; set; }
public string server { get; set; }
}
void CreateTables()
{
database.CreateTable<settings>();
}
void Insert()
{
settings s = new settings();
s.server = "<none>"
s.user_name = "";
s.password = "";
database.Insert(s)
}
void Update()
{
settings s = database.Table<settings>().FirstOrDefault();
s.server = server_address.Text;
s.user_name = user_name.Text;
s.password = pass.Text;
database.Update(s)
}
I get "Cannot update settings: it has no PK" when updating, but inserting works fine. I'm using Xamarin in a PCL referencing SQLite.net. I'm new to SQlite and Xamarin, so please be verbose when asking for more detail.
UPDATE - RESOLVED
The class is in the same namespace as the place I create an instance of the database object. Simply adding the "Sqlite" to my attribute fixed the issue which is really strange.
[SQLite.PrimaryKey, SQLite.AutoIncrement]
I have been stocked for a week now on this problem and even the above solution is not working for me...
I think that the Id does not increments automatically, that's why it says :cannot update ...
What actually works for me is incrementing the PK (Id) manually...as follows.
persons.Id++;
At the moment of verifying and inserting data into the database, I just added the above code and it updated successfully.
private async void Register_Student(object sender, EventArgs e){... ...
if(!string.Equals(newPassword.Text, rePassword.Text)){
warningLabel.Text = "Enter same pwd"; ...
}
else{
persons.Id++; //solution that worked for me at insertion level
persons.UserName = newUsername.Text; //Text entered by the user
}...
}
Thanks...

Can SolrNet client run at a different machine from solr server?

I set up a solr server running in Tomcat in machine 192.168.0.113(Centos 5.5).
And I deploy a website in matchine 192.168.0.114(Windows server 2003).
I use solrnet in matchine 192.168.0.114.
The full code like bellow(which have been edited thanks to #Paige Cook):
using System;
using System.Collections.Generic;
using System.Text;
using SolrNet;
using NUnit.Framework;
using SolrNet.Attributes;
using SolrNet.Commands.Parameters;
using Microsoft.Practices.ServiceLocation;
namespace MySolrNet
{
public class Video
{
private string videoid;
[SolrField("videoid")]
public string Videoid
{
get { return videoid; }
set { videoid = value; }
}
private string videoname;
[SolrField("videoname")]
public string Videoname
{
get { return videoname; }
set { videoname = value; }
}
private string videoorigin;
[SolrField("videoorigin")]
public string Videoorigin
{
get { return videoorigin; }
set { videoorigin = value; }
}
public Video(string id, string name, string origin)
{
this.Videoid = id;
this.Videoname = name;
this.Videoorigin = origin;
}
public Video()
{
}
public void FixtureSetup()
{
Startup.Init<Video>("http://192.168.0.113:8070/solr");
}
public void Add()
{
Video p = new Video("1", "test video", "Solr Test");
ISolrOperations<Video> solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
solr.Add(p);
solr.Commit();
}
}
[TestFixture]
public class VideoTests
{
[TestFixtureSetUp]
public void FixtureSetup()
{
Startup.Init<Video>("http://192.168.0.113:8070/solr");
}
[Test]
public void Add()
{
Video p = new Video("1", "test video", "Solr Test");
ISolrOperations<Video> solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
solr.Add(p);
solr.Commit();
}
[Test]
public void Query()
{
ISolrOperations<Video> solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
SolrQueryResults<Video> results = solr.Query(new SolrQueryByField("videoid", "33013"));
Assert.AreEqual(1, results.Count);
Console.WriteLine(results[0].Videoname);
}
}
}
However,both Add and Query test fail.
It complains: TestFixture failed: SetUp : System.IO.FileLoadException : Could not load file or assembly“SolrNet, Version=0.4.0.2002, Culture=neutral, PublicKeyToken=bc21753e8aa334cb” Or one of its dependencies.
But I have add reference to Microsoft.Practices.ServiceLocation.dll and SolrNet.dll in my projoect,is there any other dll files I just miss?
By the way,,I can access my solr sever in browser with this url:http://192.168.0.113:8070/solr.
Can anyone tell me:
Can I run solrnet and solr in different machines?
How to do it.
Thanks a lot!
I don't understand why you're using two different URLs when you Init Solr. Try changing the URL in Paige's application to the one you posted in your original question: http://192.168.0.113:8070/solr
Thanks for posting the code. The first thing I see is that you are using the test class as the class type to pass data to Solr. Split those out, that might be causing some issues. I would suggest the following:
public class Video
{
private string videoid;
[SolrField("videoid")]
public string Videoid
{
get { return videoid; }
set { videoid = value; }
}
private string videoname;
[SolrField("videoname")]
public string Videoname
{
get { return videoname; }
set { videoname = value; }
}
private string videoorigin;
[SolrField("videoorigin")]
public string Videoorigin
{
get { return videoorigin; }
set { videoorigin = value; }
}
}
[TestFixture]
public class VideoTests
{
[TestFixtureSetUp]
public void FixtureSetup()
{
Startup.Init<Video>("http://192.168.0.113/solr");
}
[Test]
public void Add() {
Video p = new Video("1","test video","Solr Test");
ISolrOperations<Video> solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
solr.Add(p);
solr.Commit();
}
[Test]
public void Query()
{
ISolrOperations<Video> solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
SolrQueryResults<Video> results = solr.Query(new SolrQueryByField("videoid", "33013"));
Assert.AreEqual(1, results.Count);
Console.WriteLine(results[0].Videoname);
}
}
Update:
Try this in a console application and see if it works...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SolrNet;
using Microsoft.Practices.ServiceLocation;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
Startup.Init<Video>("http://192.168.0.113:8070/solr");
var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Video>>();
var video = new Video("1", "test", "test");
solr.Add(video);
solr.Commit();
var results = solr.Query(SolrQuery.All);
Console.WriteLine("{0} - {1} - {2}",
results[0].Videoid, results[0].Videoname, results[0].Videoorigin);
}
}
public class Video
{
public Video(string id, string name, string origin)
{
Videoid = id;
Videoname = name;
Videoorigin = origin;
}
public string Videoid { get; set;
public string Videoname { get; set; }
public string Videoorigin { get; set; }
}
}
Can you check your project setup as suggested by Paige?
Do you have SolrNet source code added as project reference in your solution?
If you are using the dll, can you paste your .csproj file contents? If it is urgent, download the source code and add as project reference in your solution until you figure out the issue.

Local Database Samples in Windows Phone 7?

Any Samples on Local Database in windows Phone 7?i haven't work on it till now.So,
Please give some idea on that.How to save data in windows phone 7.
There are some good examples on the internet:
Simple WP7.1 local databases
WP7 Mango Local Database Support
The official documentation is quite rich in this area (apologies for the link dump):
How to: Create a Basic Local Database Application for Windows Phone
How to: Create a Local Database Application with MVVM for Windows Phone
How to: Deploy a Reference Database with a Windows Phone Application
Walkthrough: Updating a Local Database Application for Windows Phone
There are also good overview documentation:
Local Database Overview for Windows Phone
Local Database Best Practices for Windows Phone
Local Database Migration Overview for Windows Phone
First we have to create local database table.
namespace DatabaseSample.Db
{
[Table]
public class tblStudentDetails
{
[Column(CanBeNull = false)]
public string name
{
get;
set;
}
[Column(CanBeNull = false)]
public string std
{
get;
set;
}
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int id
{
get;
set;
}
}
}
After that we can create a database context
namespace DatabaseSample.Db
{
public class dbDataContext : DataContext
{
public dbDataContext(string connectionString)
: base(connectionString)
{
}
public Table<tblStudentDetails> studentDetails
{
get
{
return this.GetTable<tblStudentDetails>();
}
}
}
}
After that we can connect to the database and can insert value to the table
public class ConnectTable
{
private const string Con_String = #"isostore:/Db.sdf";
public ConnectTable()
{
using (Db.dbDataContext context = new Db.dbDataContext(Con_String))
{
if (!context.DatabaseExists())
{
// create database if it does not exist
context.CreateDatabase();
}
}
}
#region StudentDetails
public void AddToTableSDetails(string name,string standard)
{
using (Db.dbDataContext context = new Db.dbDataContext(Con_String))
{
Db.tblStudentDetails sd = new Db.tblStudentDetails();
sd.name = name;
sd.std = standard;
context.studentDetails.InsertOnSubmit(sd);
context.SubmitChanges();
}
}
public IList<Db.tblStudentDetails> GetSDetails()
{
IList<Db.tblStudentDetails> sList = null;
using (Db.dbDataContext context = new Db.dbDataContext(Con_String))
{
IQueryable<Db.tblStudentDetails> stQuery = from c in context.studentDetails select c;
sList = stQuery.ToList();
}
return sList;
}
/* public void DeleteSDetails()
{
using (Db.dbDataContext context = new Db.dbDataContext(Con_String))
{
IQueryable<Db.tblStudentDetails> stQuery = from c in context.studentDetails select c;
foreach (var value in stQuery)
{
context.studentDetails.DeleteOnSubmit(value);
}
context.SubmitChanges();
}
}*/
#endregion
}

Resources