Azure Mobile Services Identity Column Not Assigned While Offline - c#

I'm using the Azure Mobile Services .NET backend with Xamarin.Forms and I'm having an issue with using int identity ID columns. When in an offline scenario, I can successfully add the record to the DB, but the CustomerId column which is an identity remains at 0. Once online, when I sync, the value is set by SQL server and populated on the mobile device.
As the ID is required as I also need to create related data in another table, the question is, how can I get/set an ID for an entity before it's sync'd with the server? I can't set it manually as it may clash with another client. I am suing an existing SQL database, so would prefer not to have to entirely change the scheme to change the ID to use strings or guid's.
public class Customer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CustomerId { get; set; }
public string Name { get; set; }
....
}
public async Task SaveCustomer(Customer item) {
await CustomerTable.InsertAsync (item);
}

The scenario you are mentioning is exactly why Azure Mobile Apps uses strings for IDs. If you use a string, you can generate a GUID for the ID and use that prior to sync.
The only way to get the Id that is generated by the database is to sync the table.

Related

Getting the user information from the database in ASP.NET Core

I am making a website that uses the default EF Core to manipulate user data. It has a custom user with a definition like:
class AppUser : IdentityUser
{
[ProtectedPersonalData]
public Address HomeAdress { get; set; }
[ProtectedPersonalData]
public Address BusinessAddress { get; set; }
...
}
It also has the same default stuff like Email, UserName, etc., which are the same as the IdentityUser. However, I noticed that when saving the addresses to the database a new table is made for Address class where a new table entry is created for each instance of Address in my user class and the Id of the Address in the Address table is stored in HomeAddressId and BusinessAddressId of my users' database entries.
Considering this information how should I receive the user information from the database, including the Address data? I aim to get every field in the user data and also get the "related" data. Should I just make a database connection and receive stuff with SQL? Is there a way to do this using UserManager?
Side Question: Is this the most efficient way to store the Address data?

Mobile Offline Sync database on Xamarin form

Currently looking at the Enable Offline Sync for Xamarin Form : https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-xamarin-forms-get-started-offline-data.
I am having the code running on mobile and the backend run and created ToDoList table with 2 entries. The table created in ToDoList has UpdateAt, Version and Deleted columns create from the controller which extends TableController.
In existing web application currently already using the database with tables, do I have to create all the tables with UpdateAt, Version and Deleted columns. I am unsure how this data generated for those columns in web application so that both mobile and web data can be consistent.
This free online book will go through details of getting the backend setup.
https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/dataconcepts/
One of the ways described is to you EF already built in Code-First with migrations, and have a base class that looks like this
public abstract class TableData
{
public string Id { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public byte[] Version { get; set; }
}
Those are the table properties missing you asked about.

Xamarin sqlite mapping models to database table

I have deployed a database file for a xamarin project using the following guide. http://arteksoftware.com/deploying-a-database-file-with-a-xamarin-forms-app/
I created a model class as such:
[Table ("Person")]
public class Person
{
[PrimaryKey, AutoIncrement, Column("Id")]
public int Id { get; set; }
[NotNull, Column("Actor_Id")]
public int ActorId { get; set; }
}
When I try to do an insert in the repository
dbConn.Insert(newPerson);
I'm getting SQLite.Net.SQLiteException: table Person has no column named ActorId.
If the column name in the database is Actor_Id shouldn't the [Column] attribute in the model map it to the table.
There is a chance that your phone/emulator is previously deployed with app that with older database schema.
In this case, you will need to:
Remove the existing app in your phone/emulator. Then the next run should be OK due to it is created using new database schema. OR
Perform database upgrade script to change the schema of the current old database. Only do this if your app is already publish to store.
I found the problem to be that I was using the SQLite library in the model. Changing it to use SQLite.Net.Attributes allowed the correct mapping.
using SQLite.Net.Attributes;

WCF DataContract mismatch

We have this middle tier (WCF) deployed in a IIS. Sometime, DataContact changes property data type. i.e (StudentID)
From:
[DataContact]
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
}
To:
[DataContact]
public class Student
{
public string StudentID { get; set; }
public string Name { get; set; }
}
Question: Is there a way to tell the client or send a message (error) to client that the DataContract changed?
WCF support versioning capabilities.
However, when you Modify return value types then An exception will occur if the return value from the service cannot be converted to the expected data type in the client version of the operation signature.
The important distinction to understand is that there are certain changes which are breaking and other non-breaking changes. For e.g. If you add a new method to the WCF Service, then it's a Non-Breaking change, but if you remove the method it's a breaking change for the clients.
For Additional reading, read here at msdn
During the design for WCF Services, it is recommended to Services version tolerant, so that client on different version can work with the Service. Also, you would need to communicate the changes using email/document etc. I do not believe there is out of box support for Managing notifications. It appears to be an administrative work for which you can otherwise do using other communication medium like emails etc.

Asp.net MVC 5 & Identity / Restricting Data By User / IdentityXXX vs AspNetXXX tables

I'm new to MVC 5 and trying to get my head around the new Identity membership system, so forgive my newbie/ignorance on the subject.
My goal... Restrict data sent back to the user to make sure it's the user's data. I am using Entity Framework and have a set of APIs exposing data for a SPA app. On top of adding [Authorize] to the APIs, I need to (of course) also make sure the data getting retrieved is only the user's data, e.g. if I have a travel site, I only want to return that user's reservations not all in the system.
What I have done so far... I started a new MVC project so I can use the Identity membership. Next, I added my existing model and data layers that contain my model for the reservation system. Success... all working as it should. In the database, I see all of my travel site tables, a set of AspnetUser tables and a set of Identity tables. Next up, link the reservation entities to the users.
So, in my model, I create links to what I think is going to be the AspNetUsers entities/tables (as this is where both external and regular users are stored --- for me only external users, fb/google/etc, are stored in the Identity tables) in several of my classes:
public class Reservation() {
... properties ...
// Add FK to link reservation to user
[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
}
... and, I'm using the standard IdentityModel.cs file...
public class ApplicationUser : IdentityUser
... but, instead, it's linking to the Identity tables. So, this does not work...
public IQueryable<Reservation> Reservations()
{
var sUserId = getUserId(); // fctn below
_repository.Reservations.Where(r => r.UserId == sUserId);
}
This foreign key is linked to the IdentityUser table, not the AspnetUser table. If the user is a locally registered user, not one using an external login (fb/google/etc), the system only adds the user in the AspnetUser table, not the IdentityUser table. This means I can't just add the user's Id to the data table because the foreign key isn't valid as the user's Id isn't in the IdentityUser table. I quickly added this function for testing in my API controller for testing:
private string getUserId() {
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
if (User.Identity.GetUserId() != null)
{
return User.Identity.GetUserId();
}
else
{
return "";
}
}
So, my question is what should I be doing here to achieve my desired result of associating data to users? Should the foreign key/table be to something different? Am I taking an incorrect approach in adding foreign key relationships back to the user tables?

Categories