简体   繁体   English

如何使用客户端中的SQLite存储将枚举存储在SQL Azure数据库中?

[英]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. 我正在开发一个应用程序,现在我停留在UWP应用程序的注册页面。

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. 因此,我为我的应用程序创建了一个后端,后端中的一些变量是枚举,例如,我有一个名为Personal的类,并且有一个枚举变量,例如该公共Gender Sex {get; set;}那就是枚举和枚举,表将该变量转换为sql Azure中的int。

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: 我正在关注Adrian Hall Book ,因此我的客户有以下课程:

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. 我知道默认情况下enum继承自Int32,但是我正尝试使此工作正常进行,因此,每次初始化后备存储时,它都会创建sqllite.db,但根据日志记录的enum类型会创建为[TEXT]类型,因此无论何时尝试在我的后端上写它会抛出HTTPStatusCode:500内部服务器错误,并且它没有在我的sqlazure数据库上写任何东西。

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: 我的错误抛出在我的pushasync方法上,这是我的同步类的类:

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. 因此,这些课程是在Adrian Hall的书籍中显示和教授的,我使用了自己的版本。 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. 在仅使用布尔值和文本的adrian halls示例中,我能够同步我的数据库而不会出现错误,我猜测它会失败,因为我使用的是枚举,有人可以为我指出使用Azure Mobile时如何对待枚举的正确方向应用程序,因为即使我摆脱了脱机支持(sqlLite存储),它仍然会失败,并且我会不断收到错误代码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. 根据op的描述,我一边检查了此问题,然后从azure门户上的“快速入门”刀片下载并运行客户端项目和服务器项目。 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: 添加新记录,请检查本地sqlite商店:

在此处输入图片说明

Call await App.MobileService.SyncContext.PushAsync(); 调用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. 有人可以向我指出使用Azure移动应用程序时如何处理枚举的正确方向,因为即使我摆脱了脱机支持(sqlLite存储),它仍然会失败,并且我会不断收到错误代码500。

Configure config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; 配置config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; under Startup.MobileApp.cs file of your mobile app project to capture the detailed error message. 在移动应用程序项目的Startup.MobileApp.cs文件下捕获详细的错误消息。 Also, you could refer here for debugging your mobile app backend. 另外,您可以在此处参考以调试您的移动应用程序后端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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