简体   繁体   中英

How to store enums in a SQL Azure Database using SQLite store in client?

I'm developing an app, right now I'm stuck at register page of my UWP app.

So I created a backend for my app and some variable in my backend are enums like for example I have a class Named Personal and it has an enum variable like this public Gender Sex{get;set;} thats and enum, whenever I seed my table that variable its converted into an int in sql Azure.

There is no problem for that, but my main problem its at my client. I'm following Adrian Hall Book , so I have the following classes at my client:

public class Personal : TableData
{
    [Required]
    [StringLength(50)]
    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }
    [Required]
    [StringLength(50)]
    [JsonProperty(PropertyName = "dadlastname")]
    public string DadLastName { get; set; }
    [Required]
    [StringLength(50)]
    [JsonProperty(PropertyName = "momlastname")]
    public string MomLastName { get; set; }
    [Required]
    [StringLength(50)]
    [JsonProperty(PropertyName = "email")]
    public string Email { get; set; }
    [Required]
    [JsonProperty(PropertyName = "sex")]
    public Gender Sex { get; set; }//ENUM TYPE
    [Required]
    [Column(TypeName = "date")]
    [JsonProperty(PropertyName = "birthdate")]
    public DateTime? BirthDate { get; set; }

    public override bool Equals(object obj)
    {
        return Equals<Personal>(obj, this);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

as you can see this is my enum:

public enum Gender : Int32
{
    [Display(Name = "EnumGenderMale")]
    Male = 0,
    [Display(Name = "EnumGenderFemale")]
    Female = 1
}

I know enum by default inherit from Int32, but I'm trying to make this work, so everytime I initialize my backing store it creates my sqllite.db but enum type according to my logging are created as type [TEXT] so whenever I try to write on my backend it throws a HTTPStatusCode: 500 Internal server error, and it doesnt write anything on my sqlazure db.

I'm guessing the main problem its because I use enums its there a best practice in order to use enums in client and being able to write on my backend?

my errors are thrown at my pushasync methods this are my classes for my sync class:

public async Task SyncOfflineCacheAsync()
    {
        await InitializeAsync();

        try
        {
            await client.SyncContext.PushAsync();
        }
        catch (MobileServicePushFailedException ex)
        {
            if(ex.PushResult != null)
            {
                foreach (var error in ex.PushResult.Errors)
                {
                    var objString = error.Item.ToString();
                    await ResolveAnyConflictAsync(error, objString);
                }
            }
        }
        catch(Exception ex)
        {
            Debug.WriteLine($"Database corrupted, purging database: {ex.Message}");
            //purge database
        }

        //Pull each sync table
        var accountTable = await GetSyncTableAsync<Account>();
        await accountTable.PullAsync();

        var personalTable = await GetSyncTableAsync<Personal>();
        await personalTable.PullAsync();

        var laborTable = await GetSyncTableAsync<Labor>();
        await laborTable.PullAsync();

        var subscriptionTable = await GetSyncTableAsync<Subscription>();
        await subscriptionTable.PullAsync();
    }

public async Task InitializeAsync()
    {
        //Short circuit to database if its already initialized.
        if(client.SyncContext.IsInitialized)
        {
            Debug.WriteLine($"InitializedAsync: Short Circuit");
            return;
        }

        //create a reference to the local sqlLite store.
        Debug.WriteLine("InitializeAsync: Initializing store");
        var store = new MobileServiceSQLiteStoreWithLogging("ceneam.db", true, true);

        //Define Database Schema            
        store.DefineTable<Account>();
        store.DefineTable<Personal>();
        store.DefineTable<Labor>();
        store.DefineTable<Subscription>();

        //Actually create the store and update the schema.
        Debug.WriteLine("InitializeAsync: Initializing SyncContext");
        await client.SyncContext.InitializeAsync(store);

        //Do the sync
        Debug.WriteLine("InitializeAsync: Syncing Ceneam Offline Cache");
        await SyncOfflineCacheAsync();
    }

public static async Task ResolveAnyConflictAsync(MobileServiceTableOperationError error, string objString)
    {
        switch (GetModelErrorType(objString))
        {
            case "Account":
                {
                    await ResolvePushConflictAsync<Account>(error);
                    break;
                }
            case "Personal":
                {
                    await ResolvePushConflictAsync<Personal>(error);
                    break;
                }
            case "Labor":
                {
                    await ResolvePushConflictAsync<Labor>(error);
                    break;
                }
            case "Subscription":
                {
                    await ResolvePushConflictAsync<Subscription>(error);
                    break;
                }
        }
    }

    static async Task ResolvePushConflictAsync<T>(MobileServiceTableOperationError error) where T : TableData
    {
        Debug.WriteLine($"Resolve conflict for {error.Item}");
        var serverItem = error.Result.ToObject<T>();
        var localItem = error.Item.ToObject<T>();

        // Note that you need to implement the public override Equals(TableModel item)
        // method in the Model for this to work
        if(serverItem.Equals(localItem))
        {
            //Items are the same, so ignore the conflict
            await error.CancelAndDiscardItemAsync();
            return;
        }

        //Client wins
        localItem.Version = serverItem.Version;
        await error.UpdateOperationAsync(JObject.FromObject(localItem));

        //Server wins
        //await error.CancelAndDiscardItemAsync();
    }

so this classes are shown and taught at Adrian Hall books I had applied my own versions of that book. in adrian halls example which only uses booleans and text i'm able to sync my database without errors i'm guessing its failing because i'm using enums, can somebody point my in the right direction on how to treat enums when using Azure Mobile Apps, because even If I get rid of Offline support (sqlLite store) it keeps failing and I keep getting error code 500.

According to op's description, I checked this issue on my side and Download and run the client project and server project from Quick start blade on azure portal. It could work as expected on my local side, you could refer to my test as follows:

Server model:

public class ToDoItem : EntityData
{
    public string Text { get; set; }
    public bool Complete { get; set; }
    public Gender Sex { get; set; }
}

public enum Gender
{
    [Display(Name = "EnumGenderMale")]
    Male = 0,
    [Display(Name = "EnumGenderFemale")]
    Female = 1
}

Client model:

public class TodoItem
{
    public string Id { get; set; }

    [JsonProperty(PropertyName = "text")]
    public string Text { get; set; }

    [JsonProperty(PropertyName = "sex")]
    public Gender Sex { get; set; }
}

public enum Gender
{
    [Display(Name = "EnumGenderMale")]
    Male = 0,
    [Display(Name = "EnumGenderFemale")]
    Female = 1
}

Access the data via the browser:

在此处输入图片说明

Client app:

在此处输入图片说明

Add a new record, check the local sqlite store:

在此处输入图片说明

Call await App.MobileService.SyncContext.PushAsync(); , use fiddler to capture the network traces as follows:

在此处输入图片说明

can somebody point my in the right direction on how to treat enums when using Azure Mobile Apps, because even If I get rid of Offline support (sqlLite store) it keeps failing and I keep getting error code 500.

Configure config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; under Startup.MobileApp.cs file of your mobile app project to capture the detailed error message. Also, you could refer here for debugging your mobile app backend.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM