Using Realm dotnet 2.1.0 in a Xamarin Forms project, I'm unable to delete the database due to the "Unable to delete Realm because it is still open" message.
This has only been an issue since upgrading to 2.1.0, previously we were using Realm 0.80.
Here's our full database removal method:
public void RemoveDatabase()
{
// Remove all content.
try
{
ClearCachedDataItems();
}
catch (Exception ex)
{
//Logging removed
}
try
{
// Close all connections
using (var realm = GetRealmInstance())
{
if (realm != null)
{
realm.Dispose();
}
}
}
catch (Exception ex)
{
//Logging removed
}
try
{
// Drop the nuke.
var config = GetRealmConfiguration();
var delete = false;
using (var realm = Realms.Realm.GetInstance(config))
{
if (config != null)
{
delete = true;
}
realm.Dispose();
}
if (delete)
{
Realms.Realm.DeleteRealm(config); // fails here
}
}
catch (Exception ex)
{
//Logging removed
}
}
public Realms.Realm GetRealmInstance()
{
var config = GetRealmConfiguration();
if (config == null)
{
return null;
}
return Realms.Realm.GetInstance(config);
}
I added the using statements based on this git post: https://github.com/realm/realm-dotnet/issues/1545
Is there a way to get all running instances of local Realms?
I'm also concerned that I'm creating a new instance of Realm in the final steps when I just want to check a local instance.
Related
I'm writing a simple application that uses Asp.NET 6 And This method update the database schema in run time but my problem is when migration throw an exception transaction.Rollback() not work
what should I do to solve this problem
this is my method
public async Task Initialize()
{
using (var serviceScope = _scopeFactory.CreateScope())
{
using (var context = serviceScope.ServiceProvider.GetService<PMOracleDbContext>())
{
using ( var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
await context.Database.MigrateAsync();
dbContextTransaction.Commit();
}
catch (Exception e)
{
await dbContextTransaction.RollbackAsync();
Console.WriteLine(e);
throw;
}
}
}
}
}
and this my Program.cs
#region PmInitialDb
services.AddScoped<IPmDbInitializer, PmDbInitializerService>();
var dbInitializer = services.BuildServiceProvider().GetService<IPmDbInitializer>();
dbInitializer.Initialize();
dbInitializer.SeedData();
#endregion
and I use the OracelDb
I'm using, Xero sdk for my .net project(using Xero.NetStandard.OAuth2.Api;using Xero.NetStandard.OAuth2.Model.PayrollAu;)
public XeroAuth _xeroAuth;
public PayrollAuApi ipayrollAUApi = new PayrollAuApi(); //*************
private Xero.NetStandard.OAuth2.Model.PayrollAu.Employee _GetEmpLeave;
// get perticular Employee all data
private async Task<Xero.NetStandard.OAuth2.Model.PayrollAu.Employee> GetEmployeeAsync(Guid
syncedEmpID)
{
var tokens = await _xeroAuth.GetXeroTokenAuthorization();
_tenantUniqueId = tokens.Item3;
try
{
return ipayrollAUApi.GetEmployeeAsync(tokens.Item1, tokens.Item2,
syncedEmpID).Result._Employees;
}
catch (Exception ex)
{
logging.LoggingToText(ex, await _Context.GetAssemblyInfoAsync(4));
return null;
}
}
in this GetEmployeeAsync method showing casting error it look like this
how to resolve this issue
I am using lightDB as a local database in my iOS and android app implemented in Xamarin Forms. I am trying to store my local liteDB in the cloud using Azure. We have implemented a REST api which can receive a byte[] but I am having problem getting the liteDB documents to a byte[]. If I try to read the file using File.ReadAllBytes(LiteDbPath) where we have stored the liteDB i get a System.IO.IOException: Sharing violation on path. I assume this is not the way to do this, but I am unable to figure out how to do this. Anyone have any suggestions on how to do this?
It is possible I am using this the wrong way, I am quite unexperienced in this area.
Update: More details to make it clearer what I have done and what I want to do.
This is our DataStore class (where we use LiteDB):
[assembly: Dependency(typeof(DataStore<Zystem>))]
namespace AirGlow_App.Services {
class DataStore<T> {
public void Close()
{
var db = new LiteRepository(LiteDbPath);
db.Dispose();
}
public LiteQueryable<T> Get()
{
using (var db = new LiteRepository(LiteDbPath))
{
try
{
return db.Query<T>();
}
catch (Exception ex)
{
Debug.WriteLine($"Exception when doing Get. Exception = {ex.Message}.", TypeDescriptor.GetClassName(this));
//TODO : General Error Handling
return null;
}
}
}
public T Get(BsonValue id)
{
using (var db = new LiteRepository(LiteDbPath))
{
try
{
return db.Query<T>().SingleById(id);
}
catch (Exception ex)
{
Debug.WriteLine($"Exception when doing Get. Exception = {ex.Message}.", TypeDescriptor.GetClassName(this));
//TODO : General Error Handling
return default(T);
}
}
}
public void Add(T obj)
{
using (var db = new LiteRepository(LiteDbPath))
{
try
{
db.Insert<T>(obj);
}
catch (Exception ex)
{
Debug.WriteLine($"Exception when doing Add. Exception = {ex.Message}.", TypeDescriptor.GetClassName(this));
//TODO : General Error Handling
}
}
}
public void Delete(Guid Id)
{
using (var db = new LiteRepository(LiteDbPath))
{
try
{
var o = new BsonValue(Id);
db.Delete<T>(o);
}
catch (Exception ex)
{
Debug.WriteLine($"Exception when doing Delete. Exception = {ex.Message}.", TypeDescriptor.GetClassName(this));
//TODO : General Error Handling
}
}
}
public void Save(T obj)
{
using (var db = new LiteRepository(LiteDbPath))
{
try
{
db.Update<T>(obj);
}
catch (Exception ex)
{
Debug.WriteLine($"Exception when doing Save. Exception = {ex.Message}.", TypeDescriptor.GetClassName(this));
//TODO : General Error Handling
}
}
}
}
}
Then we are using it like this:
public class ZystemsViewModel : ObservableObject
{
private DataStore<Zystem> DB = DependencyService.Get<DataStore<Zystem>>();
public ZystemsViewModel()
{
MessagingCenter.Subscribe<ZystemAddViewModel, Zystem>(this, "Add", (obj, item) =>
{
var newItem = item as Zystem;
Debug.WriteLine($"Will add {newItem.Name} to local database.", TypeDescriptor.GetClassName(this));
DB.Add(newItem);
});
}
}
It was a colleague who is not working here anymore who did these parts. I think the reasoning for using it as a DependencyService was to be able to access it in all classes, pretty much as a singleton. This should probably be changed to a singleton class instead?
Using the database works fine the app. But I want to upload the entire database (file) to Azure and I am unable to get it to a byte[]. When I do
byte[] liteDbFile = File.ReadAllBytes(LiteDbPath);
I get a System.IO.IOException: Sharing violation on path. As some are suggesting it is probably due to the file is being locked, any suggestions on how to solve this?
LiteDB is plain file database and has no running service to access data. If you create a REST API, you should locate you datafile in same machine (local disk) that are running your IIS.
Azure blob storage is another service and deliver file as request.
Think LiteDB as a simple FileStream class (that works with local file) with "super-powers" :)
I making an app using xamarin and azure mobile service. I am attempting to add offline sync capabilities but I am stuck. I have a service which looks like this
class AzureService
{
public MobileServiceClient Client;
AuthHandler authHandler;
IMobileServiceTable<Subscription> subscriptionTable;
IMobileServiceSyncTable<ShopItem> shopItemTable;
IMobileServiceSyncTable<ContraceptionCenter> contraceptionCenterTable;
IMobileServiceTable<Member> memberTable;
const string offlineDbPath = #"localstore.db";
static AzureService defaultInstance = new AzureService();
private AzureService()
{
this.authHandler = new AuthHandler();
this.Client = new MobileServiceClient(Constants.ApplicationURL, authHandler);
if (!string.IsNullOrWhiteSpace(Settings.AuthToken) && !string.IsNullOrWhiteSpace(Settings.UserId))
{
Client.CurrentUser = new MobileServiceUser(Settings.UserId);
Client.CurrentUser.MobileServiceAuthenticationToken = Settings.AuthToken;
}
authHandler.Client = Client;
//local sync table definitions
//var path = "syncstore.db";
//path = Path.Combine(MobileServiceClient.DefaultDatabasePath, path);
//setup our local sqlite store and intialize our table
var store = new MobileServiceSQLiteStore(offlineDbPath);
//Define sync table
store.DefineTable<ShopItem>();
store.DefineTable<ContraceptionCenter>();
//Initialize file sync context
//Client.InitializeFileSyncContext(new ShopItemFileSyncHandler(this), store);
//Initialize SyncContext
this.Client.SyncContext.InitializeAsync(store);
//Tables
contraceptionCenterTable = Client.GetSyncTable<ContraceptionCenter>();
subscriptionTable = Client.GetTable<Subscription>();
shopItemTable = Client.GetSyncTable<ShopItem>();
memberTable = Client.GetTable<Member>();
}
public static AzureService defaultManager
{
get { return defaultInstance; }
set { defaultInstance = value; }
}
public MobileServiceClient CurrentClient
{
get { return Client; }
}
public async Task<IEnumerable<ContraceptionCenter>> GetContraceptionCenters()
{
try
{
await this.SyncContraceptionCenters();
return await contraceptionCenterTable.ToEnumerableAsync();
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
}
return null;
}
public async Task SyncContraceptionCenters()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
//await this.Client.SyncContext.PushAsync();
await this.contraceptionCenterTable.PullAsync(
//The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
//Use a different query name for each unique query in your program
"allContraceptionCenters",
this.contraceptionCenterTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling. A real application would handle the various errors like network conditions,
// server conflicts and others via the IMobileServiceSyncHandler.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
Debug.WriteLine(#"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
}
}
}
I am getting this error:
System.NullReferenceException: Object reference not set to an instance of an object. When the SyncContraceptionCenters() is run. As far as I can tell I reproduced the coffeeItems example in my service But I am stuck.
I think I found the solution. The issue was the way the tables were being synced.
by calling SyncContraceptionCenters() and SyncShop() at the same time shopItemtable.PullAsync and contraceptionTable.PullAsync were happening at the same time. Which is bad apparently bad. So but putting them in the same method and awaiting them they run separately and they work as expected.
I use wsDualHttpBinding in a wcf service, and i use the following code to store client channels:
public static void Subscribe()
{
try
{
// Subscribe the guest to the beer inventory
var guest = OperationContext.Current.GetCallbackChannel<ILoggingServiceCallBack>();
if (!CallbackList.Contains(guest))
{
CallbackList.Add(guest);
}
}
catch (Exception ex)
{
//do stuff
}
finally
{
//do stuff
}
}
and i call back clients like that:
public static void LoggingCallBack(Action<ILoggingServiceCallBack> callbackNotification)
{
try
{
if (OperationContext.Current != null)
{
var guest = OperationContext.Current.GetCallbackChannel<ILoggingServiceCallBack>();
if (!CallbackList.Contains(guest))
{
CallbackList.Add(guest);
}
}
foreach (var LoggingCallBack in CallbackList)
{
var temp = LoggingCallBack;
try
{
new Thread(() =>
{
try
{
callbackNotification(temp);
}
catch (Exception ex)
{
//do something
}
}).Start();
}
catch (Exception ex)
{
//do somethin
}
}
}
catch (Exception ex)
{
//doing something
}
finally
{
//doing something
}
}
im running through some troubles:
i have no way to tell if the client is online or not before i call
it back.
i need to be able to remove the client after no activity from the
list i guess i would be able to do that if i achieved number 1.
what is the best way to identify clients, in other words what is
the best unique identifier i can identify the client with?
if a connection with the client faulted i don't know how to detect
that and start new one from the client as if i tried to do that it refuse to and it throw exception that the connection is faulted.
sorry if i have asked more than one question, please give your opinion about the code i posted and any answer to any question of the above.