Azure Mobile App Offline Sync never got data - c#

I'm creating Windows 10 Store application and I have a problem when calling PullAsync method. I was using Azure Mobile App for a long time and I always used private IMobileServiceTable<MyTable> table. Now, I need to add support of something in Microsoft called Offline Sync. Following instruction, I didn't succeeded.
Here's my code.
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
private IMobileServiceSyncTable<MyTable> OffTable = App.MobileService.GetSyncTable<MyTable>();
private IMobileServiceTable<MyTable> OnTable = App.MobileService.GetTable<MyTable>();
protected ovveride async OnNavigatedTo()
{
if(!App.MobileService.SyncContext.IsInitialized)
{
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<MyTable>();
await App.MobileService.SyncContext.InitializeAsync(store);
}
await OffTable.PullAsync("uniqueID", OffTable.CreateQuery());
var data = await OffTable.ToCollectionAsync(); //return -> nothing
var data2 = await OnTable.ToCollectionAsync(); //return -> 50 rows
}
And MyTable.cs
using Microsoft.WindowsAzure.MobileServices;
using Newtosoft.Json;
[DataTable("MyTable")]
public sealed class MyTable
{
[JsonProperty]
public int ID { get; set;}
[JsonProperty]
public string Field1 { get; set; }
//...
[JsonProperty(PropertyName = "version")]
[Version]
public string Version { get; set; }
[JsonProperty(PropertyName = "deleted")]
[Deleted]
public bool Deleted { get; set; }
[JsonProperty(PropertyName = "updatedAt")]
[UpdatedAt]
public DateTime UpdatedAt { get; set; }
[JsonProperty(PropertyName = "createdAt")]
[CreatedAt]
public DateTime CreatedAt { get; set; }
}
Here's values from project.json:
"Microsoft.Azure.Mobile.Client": "2.0.1",
"Microsoft.Azure.Mobile.Client.SQLiteStore": "2.0.1"
What I'm doing wrong?

Problem was on the server side.
So, basically you need to create Table via Azure Portal. You can create via SQL Management Studio as well, but when creating via Portal, you will have createdAt, updatedAt, version and deleted in right format. So, if you created table via SQL MGMNT Studio, go to Portal and click Create Table, enter your table's name. It's OK, your data WILL NOT be overwritten and then everything should work fine.

Related

Xamarin.Fomrs SQLite DateTime not inserted properly through Query

In my Xamarin.Forms app, I am generating queries at api side and I directly want to execute it in my local db.
I have a table like this.
[Table("TblUnit")]
public class TblUnit
{
[AutoIncrement, PrimaryKey]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsFavourite { get; set; }
public int WebId { get; set; }
public int CompanyId { get; set; }
public DateTime OpeningStockDate { get; set; }
}
When I try to add object using InsertAsync(object) method, object is inserted with proper date. But when I try to fire query, date is not added to database. After firing query when I try to fetch data from this table OpeningStockDate comes as 01/01/0001.
//this is generated at api side and I directly want to fire query in my local sqlite db
var query = "insert into [TblUnit] (Name,Description,IsFavourite,WebId,CompanyId,OpeningStockDate) values('Bag','Description',true,12,185,'2021-03-04 10:00:00')";
I tried changing date format to mm/dd/yyyy as well. But no success.
I tried setting storeDateTimeAsTicks flag to false.
static readonly Lazy<SQLiteAsyncConnection> lazyInitializer = new Lazy<SQLiteAsyncConnection>(() =>
{
return new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags,false);
});
But then my entire app starts behaving incorrect. I can not get data from this table. It shows datetime parsing exception. Also can not add data to the table using InsertAsync method.
What I am doing wrong here ? Please tell me.
Thanks

How do I update my database without having to wipe it each time I save data to it

I've currently built a Visual Studio C# project that saves API data into a database through Entity Framework. Every time I run the project the table in the database is wiped then data is re-added again. This is to stop duplication. However, I'm wondering if there is an alternate route where I don't have to wipe the data but I can just add new data that isn't already there?
Here is the code in my project. Starting from the method in my main class that uses RestSharp to obtain the API data, deserializes to a JSON format, then saves to my DB.
public static void getAllRequestData()
{
var client = new RestClient("[My API URL]");
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
AllRequests.Rootobject result = JsonConvert.DeserializeObject<AllRequests.Rootobject>(rawResponse);
using (var db = new TransitionContext())
{
db.RequestDetails.RemoveRange(db.RequestDetails); //Wipes Data
db.RequestDetails.AddRange(result.Operation.Details); //Adds Data
db.SaveChanges();
} //Utilising EF to save data to the DB
}
} //Method that calls and stores API data
Here is the Entity Framework class below, as you can see it just supports one table (dataset).
public class TransitionContext : DbContext
{
private const string connectionString = #"[My Server]";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<AllRequests.Detail> RequestDetails { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AllRequests.Detail>().HasKey(r => r.Id);
}
}
And here is the DTO class, this holds the the data temrporarily and is used to be structured into a class fit for the API data.
public class AllRequests
{
public class Rootobject
{
public Operation Operation { get; set; }
}
public class Operation
{
public Result Result { get; set; }
public Detail[] Details { get; set; }
}
public class Result
{
public string Message { get; set; }
public string Status { get; set; }
}
public class Detail
{
[Key]
public int Id { get; set; }
public string Requester { get; set; }
public string WorkOrderId { get; set; }
public string AccountName { get; set; }
public string CreatedBy { get; set; }
public string Subject { get; set; }
public string Technician { get; set; }
public string IsOverDue { get; set; }
public long DueByTime { get; set; }
public string Priority { get; set; }
public long CreatedTime { get; set; }
public string IgnoreRequest { get; set; }
public string Status { get; set; }
}
}
Here is the table that is produced (irrelevant data blocked out).
In order to get Entity Framework working, I had to create an ID. This ID does not hold any API data, it simply starts from 1 to however many rows there are. However, WorkOrderId is a unique ID for each row. How would I be able to make this project scan for WorkOrderId's in the table and only add new data where a WorkOrderId wasn't already there?
Because ideally I want to be running this project every 5-10 minutes to keep the table constantly updated, however, at the moment I feel that wiping the table isn't the ideal way to go and is a long process. I would prefer it if I could implement this procedure instead. Any help or pointers would be greatly appreciated.
Short answer - use unique constraints and configure EF.
Long answer - you should get more familiar with databases and Entity Framework.
Database should ensure you that there are no duplicates.
Primary key (your Id here) is much more important than you think.
A table can have only one primary key, which may consist of single or multiple fields. When multiple fields are used as a primary key, they are called a composite key.
If a table has a primary key defined on any field(s), then you cannot have two records having the same value of that field(s).
(https://www.tutorialspoint.com/sql/sql-primary-key.htm)
What's more in some databases (SQL Server for example) you can have primary key built on several columns.
The other think is to properly configure Entity Framework. Basically you do this in OnModelCreating.
You can say here that a column should be unique, for example:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<User>()
.HasIndex(u => u.Email)
.IsUnique();
}
You can read more about indices here: https://en.wikipedia.org/wiki/Database_index and here: How does database indexing work?
It seems that you should make field WorkOrderId your primary key and delete Id field. I think you should also read more about foreign keys: https://www.w3schools.com/sql/sql_foreignkey.asp

How to correct database field mappings in SQLite?

I've attached an SQLite database to my Windows Phone 8.1 project. The connection is working but the results returned from the database are null.
Previously I posted a question on the null bindings of my query. But the answer suggested hasn't resolved the issue of a null result being returned, which is why I'm re-posting the question.
Debugging: Stepping through the SQLlite class I can see that the bindings are null although I don't see any reason for that considering the types in my DB schema and the associated field mappings in ZoneInfo.cs.
I query the database as follows which should map each field to my class ZoneInfo below.
using (var dbConn = new SQLiteConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, AppDBPath), true))
{
List<ZoneInfo> zoneInfo = dbConn.Query<ZoneInfo>("select * from " + tableName).ToList<ZoneInfo>();
ObservableCollection<ZoneInfo> zoneInfoCollection = new ObservableCollection<ZoneInfo>(zoneInfo);
return zoneInfoCollection;
}
Question:
How can I correct my database mappings so that the query result isn't empty?
**ZoneInfo.cs (mapping class for DB fields)**
public class ZoneInfo
{
//The ObjectId property is marked as the Primary Key
[SQLite.PrimaryKey]
[Column("objectId")]
public string ObjectId { get; set; }
[Column("zone")]
public string ZoneName { get; set; }
[Column("tariff_ph")]
public float TariffPH { get; set; }
[Column("tariff_pd")]
public float TariffPD { get; set; }
[Column("restrictions")]
public string Restrictions { get; set; }
[Column("days_of_operation")]
public string DaysOpen { get; set; }
[Column("hours_of_operation")]
public string HoursOpen { get; set; }
public ZoneInfo()
{
}
public ZoneInfo(string objectId, string zoneName, int tariffPH, int tariffPD,
string restrictions, string daysOpen, string hoursOpen )
{
ObjectId = objectId;
ZoneName = zoneName;
TariffPH = tariffPH;
TariffPD = tariffPD;
Restrictions = restrictions;
DaysOpen = daysOpen;
HoursOpen = hoursOpen;
}
}
Query Result: (You can see that the result of the query's field's are all null which isn't the case in the database:
The DB schema is as follows and this is a link to the DB file for testing:
The schema error causing the null mapping bindings, was the result of stale SQLLite database being referenced on the device.
Deleting the app from the phone and rebuilding the app via Visual Studio caused the database to be redeployed to the file system with the updated correct mappings. :)
1.From the Start screen, swipe left to display the Apps list. Alternatively from the Start screen, tap the right arrow (located in the lower-right).
2.Touch and hold an app.
3.Tap uninstall.
4.Tap yes.

Setting default values for Complex Properties - Backfilling database

I have an MVC site using code first migrations which contains an Object called "Organisation" as below:
public class Organisation
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
public virtual ICollection<Location> Locations { get; set; }
public UserPermissions Permissions { get; set; }
}
And I am trying to implement user permissions for each of the areas on my site. As a result the Permissions property has been newly added above and is an object of type UserPermissions:
public class UserPermissions
{
public PermissionLevel Contacts { get; set; }
public PermissionLevel Messages { get; set; }
public PermissionLevel Groups { get; set; }
public PermissionLevel Data { get; set; }
}
Where PermissionLevels is an enum defined as:
public enum PermissionLevel
{
Locked = 0,
View = 1,
Administrator = 2
}
I feel the structure of this implementation is fine and upon adding the migration EF creates a column in my dbo.Organisations table for each permission type (Permissions_Contacts, Permissions_Messages etc.).
The database however already has many Organisations and I wondered if there was a way of imposing a default. If I updated my database now all Permissions would be 0 (Locked), however I'd like the default to be different for each Permissions category e.g. Administrator rights for Contacts/Messages/Groups and Locked rights for Data because Data will be set up as and when a user requests it.
I will soon add functionality to the Admin tier of the site where the Organisations are created, and make the selection of UserPermissions mandatory for all areas, but I'd prefer not to have to go back through and manually change all permissions of the existing Organisations to be my defaults.
Is there a way of automatically imposing these defaults for the existing organisations within the database?
Could you just set your default permissions in the constructor of your Organisation or UserPermissions object?
Something like:
public UserPermissions()
{
Contacts = PermissionLevel.Locked;
// etc
}
or
public Organisation()
{
this.Permissions = new UserPermissions();
if (this.Id == 0) // new object not yet persisted
{
this.Permissions.Contacts = PermissionLevel.Locked;
// etc
}
}
Based on comments:
For filling the existing data that is now out of sync with your model, you'll want to update your migration script to populate the new properties in your "up" script (the "down" script should not need modification I wouldn't think).
Basically in your up script you can either write update sql statements, or iterate through the objects via the context to manipulate their values in a more strongly typed manner.
Here's some information on getting started with migration scripts:
http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application
I think your Up method could be modified to have something like this near the end:
using (MyContext context = new MyContext)
{
var orgs = context.Organisation;
foreach (Organization org in orgs)
{
org.Permissions = new UserPermissions()
{
Contacts = PermissionLevel.Locked,
// etc
}
}
context.SaveChanges();
}

EF Code First - Primary Key Data Type Change

We need to change one of our tables to use a Guid as the primary key rather than an int. This system is in use in production and it appears that this change requires some additional work rather than the usual add-migration stuff.
There are two FK references to this table meaning that there are 3 total tables needing to be modified.
How should this be handled when using Code First?
CURRENT MODEL CODE
public class TableA
{
public int Id { get; set; }
public String Name { get; set; }
public bool IsActive { get; set; }
}
DESIRED MODEL CODE
public class TableA
{
public Guid Id { get; set; }
public String Name { get; set; }
public bool IsActive { get; set; }
}
First do the change on the code and then install or host your application and create the fresh database out of the new changes. Now you have the database with the new changes. So make a diff between the one in production ( after backing it up and import it in your test server) and the fresh one ( with the new change), now you can create your upgrade script from the diff for the production. Then first upgrade the database of production and then publish your app

Categories

Resources