table mapping unable error in SQlite connection in windows application - c#

When i connect my application with SQLite database. The following exception throw.
An exception of type 'SQLite.SQLiteException' occurred in
Scrap_Book.Windows.exe but was not handled in user code
Additional information: no such table: CONTENT
I created the table with the help of SqLite manager an adon of mozila firefox.
Please help me how I can solve this problem.
var dbpath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "MYSCRAPBOOK.sqlite");
using (var db = new SQLite.SQLiteConnection(dbpath))
db.Insert(new CONTENT()
{
STICKERS=snodesticker
});
db.Commit();
db.Dispose();
db.Close();
var line = new MessageDialog("Records Inserted");
await line.ShowAsync();

According to message from your exception you haven't created CONTENT table.
So, I guess you need to create table before inserting data.
public static string DB_NAME = "ContactsManager.sqlite";
public static string DB_PATH = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, DB_NAME));//DataBase Name
private async Task<bool> CheckFileExistsAsync(string fileName)
{
try
{
var store = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
return true;
}
catch
{
}
return false;
}
if (!(await CheckFileExistsAsync(DB_NAME)))
{
using (var db = new SQLiteConnection(DB_PATH))
{
db.CreateTable<CONTENT>();
}
}

Related

Unable to open a realm at path xxx in Xamarin forms

I'm reading data from remote MongoDB realm which syncs to my local realm, but it seems I can't read from my local realm after sync.
This is the message I get when I try to read from my local realm:
Unable to open a realm at path '/data/user/0/com.companyname.appname/files/default.realm': Incompatible histories. Expected a Realm with no or in-realm history, but found history type 3 Path:Exception backtrace:\n<backtrace not supported on this platform>.
Here is my code:
private async Task<Realm> OpenRealm()
{
try
{
var user = App.realmApp.CurrentUser;
//if user is not logged on yet log on the user and sync
if (user == null)
{
var CurrentUser = await App.realmApp.LogInAsync(Credentials.Anonymous());
var config = new SyncConfiguration("Hirschs", CurrentUser);
_realm = await Realm.GetInstanceAsync(config);
return _realm;
}
else
{
return _realm = Realm.GetInstance();
}
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync(new AlertConfig
{
Title = "An error has occurred",
Message = $"An error occurred while trying to open the Realm: {ex.Message}"
});
// Try again
return await OpenRealm();
}
}
The problem here is that you are trying to create a new local realm in the same path where the synced realm already is.
I suppose that you would like to open the same realm synchronously (that is necessary if the device is offline). In this case you would just need to use the same configuration for both the sync and async calls, as reported in the documentation here.
You could do something like:
private async Task<Realm> OpenRealm()
{
try
{
var currentUser = App.realmApp.CurrentUser;
if (currentUser == null)
{
var currentUser = await App.realmApp.LogInAsync(Credentials.Anonymous());
var config = new SyncConfiguration("Hirschs", currentUser);
_realm = await Realm.GetInstanceAsync(config);
return _realm;
}
else
{
var config = new SyncConfiguration("Hirschs", currentUser);
_realm = Realm.GetInstance(config);
return _realm;
}
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync(new AlertConfig
{
Title = "An error has occurred",
Message = $"An error occurred while trying to open the Realm: {ex.Message}"
});
}
}

Cancellation Token Disposed Exception

I had this piece of code that initially worked fine. However, After adding it to a class where I store my methods that are reused, it keeps failing. The exception that is caught states that the CancellationTokenSource has been Disposed. Can someone point me in the right direction?
I have tried creating a new client and Adding CancellationToken.None to the PutAsync() method from HTTPClient Class but it still fails with the CancellationTokenSource Disposed exception.
public async void AddProduct(Product product)
{
string storeId = "";
try
{
var storeData = JObject.Parse(Connect.Json).SelectToken("store").ToString();
var stores = JsonConvert.DeserializeObject<List<Store>>(storeData);
var store = stores[0];
storeId = store.Id;
store.Products.Add(product);
ProdInfo info = new Info();
foreach(Product p in store.Products)
{
info.AddedProducts = + p.Id;
}
var content = JsonConvert.SerializeObject(info);
using (Connect.Client)
using (var response = await Connect.Client.PutAsync(_url + "/stores/" + storeId, new StringContent(content)))
{
var cont = response.Content;
string result = await cont.ReadAsStringAsync();
if ((int)response.StatusCode == 200)
{
this.JobResult = result;
//this.JobResult = "Store has been successfully updated";
}
else
{
this.JobResult = result;
//this.JobResult = "Store was not updated!";
}
}
}
catch (Exception ex)
{
//this.JobResult = "Store has not been updated due to an error.";
this.JobResult = ex.Message;
}
}
I was able to solve this by simple removing 'using(Connect.Client)' from all of my methods. As #sellotape stated, They were disposing of the HttpClient before I was able to use it again. Thank you all for your contributions.

Database is locked: SQLite exception thrown on my android and ios xamarin app

The database was very stable until I did all the package and bundle signing and deploy the app to the app center for distributed testing, then I started getting all kind of errors from the SQLite database. I did some research and got to know that the database is not threading safe, but how can I make it thread safe, all my database connections and queries are through async.
This is my database connection
private static object collisionLock = new object();
//local SQLite database.
public SQLiteAsyncConnection Db;
private Uri url;
private MemberDataStore membersStore;
private AdvantageMemberDataStore advMembersStore;
private EventDataStore eventDataStore;
public ConnectionsUtil()
{
Db = DependencyService.Get<IDatabaseConnection>().DbConnection();
}
This is the code that does inserts and updates, I have three methods like the one below that access the database and many queries that uses the Db within the app
public async Task GetAdvantageMembersAsync(AdvantageMemberDataStore store)
{
await Db.QueryAsync<AdvantageMember>("DROP TABLE IF EXISTS AdvantageMember").ContinueWith(t =>
{
Db.CreateTableAsync<AdvantageMember>();
Console.WriteLine("AdvantageMember table created!");
});
url = new Uri("http://54.39.180.209/benefits");
Console.WriteLine("Gideon: Attempting to get advantage members.");
try
{
string json;
//Gideon: get json string containing advantage members.
using (WebClient sr = new WebClient())
{
Console.WriteLine("Gideon: Retrieving advantage Members....");
sr.DownloadStringCompleted += async (s, e) =>
{
Console.WriteLine("Gideon: Advantage Members Downloaded. Processing advantage Members....");
json = e.Result;
lock (collisionLock)
{
Db.InsertAllAsync(JsonConvert.DeserializeObject<IEnumerable<AdvantageMember>>(json)).ContinueWith(async t =>
{
await store.UpdateItemsAsync(Db.QueryAsync<AdvantageMember>("SELECT * FROM AdvantageMember GROUP BY Title").Result);
});
}
Console.WriteLine("Processing Members benefits for android");
advMembersStore = store;
};
await Task.Run(() => sr.DownloadStringAsync(url));
}
}
catch (Exception e)
{
Console.WriteLine("Gideon: An error occured while trying to dbect. ERROR: " + e);
}
}
**This is the code that specify the folder for the sqlite connection**
public class DatabaseConnection_iOS: Services.IDatabaseConnection
{
public SQLiteAsyncConnection DbConnection()
{
var dbName = "MyDb.db3";
string personalFolder =
Environment.
GetFolderPath(Environment.SpecialFolder.Personal);
string libraryFolder =
Path.Combine(personalFolder, "..", "Library");
var path = Path.Combine(libraryFolder, dbName);
return new SQLiteAsyncConnection(path);
}
}
In my case, I was put SaveContext inside foreach
var transaction = _context.Database.BeginTransaction();
try
{
foreach (var item in obj)
{
_context.EntrevistaNacionals.Add(item);
await _context.SaveChangesAsync(); //--wrong
}
transaction.Commit();
return true;
}

Items are not added in dynamodb using aws toolkit for .net

I have created a profile in aws toolkit for .net and I am creating a lambda function by uploading the aws function.
The function when tested in aws console does not throw any error. However , the data is not added in dynamodb table.
Here is the code snippet :
public void FunctionHandler(DynamoDBEvent dynamoEvent, ILambdaContext context1)
{
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
Table awsnet = Table.LoadTable(client, "bookmaster");
context1.Logger.LogLine("In method : Function Handler : start");
CreateBookItem(bookmaster);
}
private static void CreateBookItem(Table tblName)
{
var client = new AmazonDynamoDBClient();
Console.WriteLine("\n*** Executing CreateBookItem() ***");
string sampleBookId = "3";
var doc = new Document();
doc["strid"] = sampleBookId;
tblName.PutItemAsync(doc);
}
Also , all the examples are using "tblName.PutItem(doc)" , but it is unavailable. SO I have used "tblName.PutItemAsync(doc)". The log lines are printed in the aws console , but data is not added in table.
I was able to solve the above issue with the following code :
public void FunctionHandler(DynamoDBEvent dynamoEvent, ILambdaContext context1)
{
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
Table bookmaster = Table.LoadTable(client, "bookmaster");
context1.Logger.LogLine("In method : Function Handler : start");
string result = PutDataAsync(bookmaster, context1).Result;
context1.Logger.LogLine("Result = " + result);
}
private static async Task<string> PutDataAsync(Table table , ILambdaContext context1)
{
try
{
string sampleBookId = "3";
var doc = new Document();
doc["strid"] = sampleBookId;
Document x = await table.PutItemAsync(doc);
context1.Logger.LogLine("In method after put item async");
return "success";
}
catch(Exception ex)
{
context1.Logger.LogLine("In method after put item async catch block");
return "failed";
}
}

Server to Client back to server synchronization

I am developing a WPF application that interacts with localdb using the Entity Framework 6.0
So the past couple of weeks I've been attempting to get synchronization setup between the following database types:
Server: SQL Server 2008 Database
Client: localdb (SQL Express)
While I can get the structure of the database from the server transferred onto the client it does not bring over the relationships.
This somehow changes the way the ADO.NET Entity Data Model is generated.
When the Entity Data Model is generated for the server structure it generates the many-to-one-to-many relationships as a collection (many-to-many), but on the localdb that is generated (with no relationships generated) it keeps the table structure. This causes issues with my application. I can't fully migrate to an offline application if the synchronization doesn't work properly.
Server to Client (Initialization of client):
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
namespace DatabaseSetup
{
class Program
{
static void Main()
{
try
{
CreateLocalDatabase();
ProvisionServer();
ProvisionClient();
Sync();
}
catch (Exception ex)
{
Console.WriteLine($"Exception thrown: {ex.Source}");
Console.WriteLine($"Exception thrown: {ex.Data}");
Console.WriteLine($"Exception thrown: {ex.Message}");
Console.ReadLine();
}
}
public static void CreateLocalDatabase()
{
var conn = new SqlConnection(LocalDb);
var command = new SqlCommand(#"CREATE DATABASE ********", conn);
try
{
conn.Open();
Console.WriteLine(command.ExecuteNonQuery() <= 0
? #"Creating '********' Database on '(localdb)\v11.0'"
: #"Database '********' already exists. Attempting to synchronize.");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if(conn.State == ConnectionState.Open)
conn.Close();
}
}
public static void ProvisionServer()
{
Console.WriteLine(#"Attempting to provision server for synchronization...");
// connect to server database
var serverConnection = new SqlConnection(Server);
// define a new scope named ProductsScope
var scopeDescription = DatabaseScope(serverConnection);
// create a server scope provisioning object based on the ProductScope
var serverProvision = new SqlSyncScopeProvisioning(serverConnection, scopeDescription);
if(!serverProvision.ScopeExists("DatabaseScope"))
{ // skipping the creation of table since table already exists on server
serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);
// start the provisioning process
serverProvision.Apply();
Console.WriteLine(#"Provisioning complete.");
}
else
{
Console.WriteLine(#"Server already provisioned.");
}
}
public static void ProvisionClient()
{
Console.WriteLine(#"Attempting to provision client for synchronization...");
// create a connection to the SyncExpressDB database
var clientConnection = new SqlConnection(Client);
// create a connection to the SyncDB server database
var serverConnection = new SqlConnection(Server);
// get the description of ProductsScope from the SyncDB server database
var scopeDesc = DatabaseScope(serverConnection);
// create server provisioning object based on the ProductsScope
var clientProvision = new SqlSyncScopeProvisioning(clientConnection, scopeDesc);
if (!clientProvision.ScopeExists("DatabaseScope"))
{
// starts the provisioning process
clientProvision.Apply();
Console.WriteLine(#"Provisioning complete.");
}
else
{
Console.WriteLine(#"Client already provisioned.");
}
}
public static void Sync()
{
//Define conections
Console.WriteLine(#"Attempting to synchronize.");
var serverConnection = new SqlConnection(Server);
var clientConnection = new SqlConnection(Client);
//Create Sync Orchestrator
var syncOrchestrator = new SyncOrchestrator
{
Direction = SyncDirectionOrder.DownloadAndUpload,
LocalProvider = new SqlSyncProvider("DatabaseScope", clientConnection),
RemoteProvider = new SqlSyncProvider("DatabaseScope", serverConnection)
};
((SqlSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += Program_ApplyChangeFailed;
var syncStats = syncOrchestrator.Synchronize();
Console.WriteLine("\n\nSynchronization complete:");
Console.WriteLine($"Start Time: {syncStats.SyncStartTime}");
Console.WriteLine($"Uploaded: {syncStats.UploadChangesTotal}");
Console.WriteLine($"Downloaded: {syncStats.DownloadChangesTotal}");
Console.WriteLine($"Time Elapsed: {syncStats.SyncEndTime}");
Console.Read();
}
private static DbSyncScopeDescription DatabaseScope(SqlConnection connection)
{
//Define scope
var scopeTables = new Collection<DbSyncTableDescription>();
foreach (var table in TableList)
{
scopeTables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(table, connection));
}
var databaseScope = new DbSyncScopeDescription("DatabaseScope");
foreach(var table in scopeTables)
{
databaseScope.Tables.Add(table);
}
return databaseScope;
}
static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
{
// display conflict type
Console.WriteLine(e.Conflict.Type);
// display error message
Console.WriteLine(e.Error);
}
}
}
and this is the action I setup to happen when the user clicks a button on the application whenever they want to sync:
Synchronization between client and server:
using System;
using System.Collections.ObjectModel;
using System.Data.SqlClient;
using System.Windows;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Outreach.Resources;
namespace WpfApplication
{
class DatabaseSynchronization
{
public static void Sync()
{
//Define conections
Console.WriteLine(#"Attempting to synchronize.");
var clientConnection = new SqlConnection(Constants.Client);
var serverConnection = new SqlConnection(Constants.Server);
//Create Sync Orchestrator
var syncOrchestrator = new SyncOrchestrator();
syncOrchestrator.LocalProvider = new SqlSyncProvider("DatabaseScope", clientConnection);
syncOrchestrator.RemoteProvider = new SqlSyncProvider("DatabaseScope", serverConnection);
syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
((SqlSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += Program_ApplyChangeFailed;
var syncStats = syncOrchestrator.Synchronize();
Console.WriteLine("\n\nSynchronization complete:");
Console.WriteLine($"Start Time: {syncStats.SyncStartTime}");
Console.WriteLine($"Uploaded: {syncStats.UploadChangesTotal}");
Console.WriteLine($"Downloaded: {syncStats.DownloadChangesTotal}");
Console.WriteLine($"Time Elapsed: {syncStats.SyncEndTime}");
Console.Read();
}
static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
{
// display conflict type
Console.WriteLine(e.Conflict.Type);
// display error message
Console.WriteLine(e.Error);
}
private static DbSyncScopeDescription DatabaseScope(SqlConnection connection)
{
//Define scope
var scopeTables = new Collection<DbSyncTableDescription>();
foreach(var table in Constants.MsoTableList)
{
scopeTables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(table, connection));
}
var outreachScope = new DbSyncScopeDescription("DatabaseScope");
foreach(var table in scopeTables)
{
outreachScope.Tables.Add(table);
}
return outreachScope;
}
public static void ProvisionServer()
{
Console.WriteLine(#"Attempting to provision server for synchronization...");
// connect to server database
var serverConnection = new SqlConnection(Constants.Server);
// define a new scope named ProductsScope
var scopeDescription = DatabaseScope(serverConnection);
// create a server scope provisioning object based on the ProductScope
var serverProvision = new SqlSyncScopeProvisioning(serverConnection, scopeDescription);
if(!serverProvision.ScopeExists("DatabaseScope"))
{ // skipping the creation of table since table already exists on server
serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);
// start the provisioning process
serverProvision.Apply();
Console.WriteLine(#"Provisioning complete.");
}
else
{
Console.WriteLine(#"Server already provisioned.");
}
}
public static void ProvisionClient()
{
Console.WriteLine(#"Attempting to provision client for synchronization...");
// create a connection to the SyncExpressDB database
var clientConnection = new SqlConnection(Constants.Client);
// create a connection to the SyncDB server database
var serverConnection = new SqlConnection(Constants.Server);
// get the description of ProductsScope from the SyncDB server database
var scopeDesc = DatabaseScope(serverConnection);
// create server provisioning object based on the ProductsScope
var clientProvision = new SqlSyncScopeProvisioning(clientConnection, scopeDesc);
if(!clientProvision.ScopeExists("DatabaseScope"))
{
// starts the provisioning process
clientProvision.Apply();
Console.WriteLine(#"Provisioning complete.");
}
else
{
Console.WriteLine(#"Client already provisioned.");
}
}
}
}
Is there something I'm doing wrong?
Are there better options than Sync Framework?
Sync Framework don't do schema syncs. it provisions the tables just so you sync data. If you want to include the full server schema, you'll have to script it yourself and execute on the client. if you're only after synching the FKs as well, you can include that as part of the db sync table description when you provision.

Categories