Azure Mobile Apps Offline Client Throws NotSupportedException on Query - azure-mobile-services

I have a Azure Mobile Apps Xamarin.Forms PCL client and have Offline Sync enabled. I tried to Pull data from my backend and afterwards query data from the offline storage with a Where clause. That throws the following exception and I don't know why.
Sync error: 'fahrerinfo.Imei.Equals("02032032030232")' is not supported in a 'Where' Mobile Services query expression.
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await OfflineSyncStoreManager.Instance.TruckFahrerTable.PullAsync("allTruckFahrerItems",
OfflineSyncStoreManager.Instance.TruckFahrerTable.CreateQuery());
Debug.WriteLine("SyncAsync: PUSH/PULL completed.");
}
catch (MobileServicePushFailedException e)
{
Debug.WriteLine("SyncAsync: PUSH failed.");
Debug.WriteLine(e.Message);
}
catch (Exception e)
{
Debug.WriteLine("SyncAsync: PUSH/PULL failed.");
Debug.WriteLine(e.Message);
//Debugger.Break();
}
}
public async Task<ObservableCollection<TruckFahrer>> GetTruckFaherAsync(bool syncItems)
{
try
{
if (syncItems)
{
await OfflineSyncStoreManager.Instance.SyncAsync().ConfigureAwait(false);
}
var deviceInfo = DependencyService.Get<IDeviceInfo>().GetPhoneInfo();
var imeiString = deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.ImeiKey];
var imei = imeiString.Equals("000000000000000") ? deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.IdKey] : imeiString;
IEnumerable<TruckFahrer> items =
await OfflineSyncStoreManager.Instance.TruckFahrerTable
//.Where(fahrerinfo => fahrerinfo.Imei.Equals(imei)) TODO: Why does that throw an exception???
.ToEnumerableAsync();
// TODO: Because above does not work
items = items.Where(fahrer => fahrer.Imei.Equals(imei));
return new ObservableCollection<TruckFahrer>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
Debugger.Break();
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
Debugger.Break();
}
return null;
}
Thanks for any hint,
Eric

Are you a Java developer too? I'm and had this issue because in Java we need to compare strings with String#equals method, haha.
For some reason MobileServices doesn't allow us to use Equals in this situation.
To fix your problem, use == instead. As you can see here C# difference between == and Equals() both have the same effect in this case.
Where(fahrerinfo => fahrerinfo.Imei == imei)

Related

What do I return in a async task when an exception occurs

I have the following code...
public async Task<User> GetUserAsync(string name)
{
await using var db = new ApplicationDbContext(new DbContextOptions<ApplicationDbContext>());
try
{
return await db.User.SingleAsync(x => x.Name == name);
}
catch (Exception e)
{
//return new User();
}
}
I wonder what I would return if there is an exception because the query does not find a match from the database? Do I return a empty user object or what is standard procedure?
what is standard procedure?
It's normal to let exceptions propagate until you have something else you can do with them.

Opening a Postgres Connection in Xamarin returns Error While Connecting

I am trying to connect my Android Application to Postgres but seems not to work.
The Exception Message is: Exception while Connecting
This is my Code Behind,
private void Login_Clicked(object sender, EventArgs e)
{
DBInterface<DBLogicInput, DBLogicResult> dbLoginLogic = new DBLoginLogic();
DBLogicInput userInput = new DBLogicInput();
DBLogicResult DBResult = new DBLogicResult();
LoginModel useCredentials = new LoginModel()
{
userName = txtUsername.Text,
passWord = txtPassword.Text
};
userInput[typeof(LoginModel).FullName] = useCredentials;
try
{
DBResult = dbLoginLogic.DoProcess(userInput);
bool userExisting = DBResult.ResultCode != DBLogicResult.RESULT_CODE_ERR_DATA_NOT_EXIST;
if (userExisting)
{
Application.Current.MainPage = new NavigationPage(new IndexPage());
}
else
{
_ = DisplayAlert("Login Error", "User does not exist", "Ok");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This is the Class I created to connect the DB.
public abstract class DBLogic : DBInterface<DBLogicInput, DBLogicResult>
{
public string connectionString = "Server=localhost;Port=5432;User Id=postgres;Password=postgres;Database=proyektoNijuan";
public DBLogicResult DoProcess(DBLogicInput inOut)
{
//throw new NotImplementedException();
DBLogicResult result = default(DBLogicResult);
NpgsqlConnection connection = null;
NpgsqlTransaction transaction = null;
try {
connection = new NpgsqlConnection(connectionString);
if (connection.State != System.Data.ConnectionState.Open)
{
connection.Open();
}
transaction = connection.BeginTransaction();
result = Process(connection, inOut);
transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
transaction.Rollback();
} finally {
if (connection != null)
{
connection.Close();
}
}
return result;
}
protected abstract DBLogicResult Process(NpgsqlConnection conn, DBLogicInput InOuT);
}
The error exists after the debugger hits the code connection.Open();.
Should I add a web services to connect the postgres to my android app built in xamarin forms?
I am only a beginner in Xamarin Forms. I am just trying to create a self application. And need a little help for me to learn a new platform in programming.
Thank you and Regards,
How to fix it?
Well, I think I am doing it wrong.
Maybe the Right way to Connect the PostgreSQL is to have a WEB API.
Calling that web API to the Xamarin forms.
I really don't know if it is correct, but I will give it a try.
I will update the correct answer after I finish the development of that WEB API so that other beginners will found this answer helpful.

How would I delete a subscribed item in Eclipse Milo 0.3.8?

I have looked at the examples for subscribing to a NodeId and im wondering how I could stop/delete a subscription afterward.
Eclipse Milo v0.3.8 Client.
Here's what I've tried.
protected boolean unsubscribe(TransactionDefinition transactionDefinition) {
// Finds the mathing TransactionDefinition from the map where all subscriptions
// are stored, together with the clientHandle.
// private Map<UInteger, TransactionDefinition> subscriptions = new HashMap<>();
try {
UInteger subscriptionClientHandle = null;
for (Map.Entry<UInteger, TransactionDefinition> entry : subscriptions.entrySet()) {
if (entry.getValue().equals(transactionDefinition))
subscriptionClientHandle = entry.getKey();
}
if (subscriptionClientHandle == null) return false;
try {
client.getSubscriptionManager().deleteSubscription(subscriptionClientHandle).get();
return true;
} catch (Exception e) {
log.error("Subscription not found: {}", e.getMessage(), e.getCause());
e.printStackTrace();
}
} catch (ClassCastException e) {
log.error("TransactionDefinition trigger not found. {}", e.getMessage(), e.getCause());
e.printStackTrace();
}
return false;
}
UaSubscription has a deleteMonitoredItems method on it.
UaSubscriptionManager has a deleteSubscription method on it.
You could also call either of these services "manually" by invoking the "raw" service methods on the UaClient instance.

Filter data from azure database using Mobile Service client

I am trying to restrict the data returned by the Mobile App service hosted on Azure portal. Unfortunately I am unable to restrict the data before it's returned (at the createQuery() stage). The filter works only when applied after the data is returned. Here is a sample code. The app is written in Xamarin forms on iOS platform.
public async Task<IEnumerable<Company>> GetCompanies(string
cityId)
{
await App.MobileService.SyncContext.InitializeAsync(store,
handler);
this.companies = App.MobileService.GetSyncTable<Company>();
try
{
await App.MobileService.SyncContext.PushAsync();
// Filter is unsuccessful here
await this.companies.PullAsync("all_companies",
this.companies.CreateQuery().Where(x => x.City_Id ==
cityId)).ConfigureAwait(false);
}
catch (MobileServicePushFailedException ex)
{
string ErrorString = string.Format("Push failed because
of Company sync errors: {0} errors, message:
{1}",ex.PushResult.Errors.Count, ex.Message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Sync companies: " + ex);
}
// Filter works here. But its too late as it has already
// pulled all the unnecessary data
return await companies.Where(x => x.City_Id ==
cityId).OrderBy(c => c.Id).ToEnumerableAsync();
}

Write to Event Log - The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security."

I'am trying to write some messages to Windows Event log.
The (security) exception will be thrown when calling function "SourceExists()".
private bool CheckIfEventLogSourceExits()
{
try
{
if (!EventLog.SourceExists(this.BaseEventLog))
{
return false;
}
return true;
}
catch (System.Security.SecurityException)
{
return false;
}
}
All answers to this question are explaining how you can MANUALLY resolve issue.
Like here: Stackoverflow Thread. Solution would be changing some registry keys
But you can't expect that everyone who consumes your application is aware of these changes.
So my question is, how can we solve this issue programmatically?
Below my code:
try
{
string sLog = "Application";
if (CheckIfEventLogSourceExits())
{
EventLog.CreateEventSource(this.BaseEventLog, sLog);
}
EventLog.WriteEntry(this.BaseEventLog, message, eventLogEntryType);
}
catch (Exception ex)
{
ex.Source = "WriteToEventLog";
throw ex;
}
I know it's too late for this posting, but the answer, I found from similar experience, is that the service you're running under doesn't have administrative rights to the machine and, thus, can't write to the logs.
It's easy enough to figure out if an app is being run under admin rights. You can add something like this to your code with a message box advising the user to run "admin".
private void GetServicePermissionLevel()
{
bool bAdmin = false;
try {
SecurityIdentifier sidAdmin = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
AppDomain myDomain = Thread.GetDomain();
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
if (myPrincipal.IsInRole(sidAdmin)) {
bAdmin = true;
} else {
bAdmin = false;
}
} catch (Exception ex) {
throw new Exception("Error in GetServicePermissionlevel(): " + ex.Message + " - " + ex.StackTrace);
} finally {
_ServiceRunAsAdmin = bAdmin;
}
}