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

时间:2017-08-31 04:31:09

标签: c# sqlite enums uwp azure-mobile-services

我正在开发一款应用,现在我被困在我的UWP应用的注册页面。

所以我为我的应用程序创建了一个后端,后端的一些变量是枚举,例如我有一个名为Personal的类,它有一个枚举变量,如公共性别性别{get; set;}那个和枚举,每当我为变量转换为sql Azure中的int变量表。

没有问题,但我的主要问题在于我的客户。 我跟随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();
    }
}

你可以看到这是我的枚举:

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

我知道enum默认继承自Int32,但是我试图让这个工作,所以每次我初始化我的后备存储时它会创建我的sqllite.db但根据我的日志记录的枚举类型被创建为类型[TEXT因此,每当我尝试在我的后端写入时,它会抛出HTTPStatusCode:500内部服务器错误,并且它不会在我的sqlazure数据库上写任何内容。

我猜测它的主要问题是因为我使用枚举它是最好的做法,以便在客户端使用枚举并能够在我的后端写入?

我的错误是在我的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();
    }

所以这些课程在Adrian Hall的书籍中展示和教授,我已经应用了我自己的那本书。在adrian halls的例子中,我只使用布尔和文本,我可以毫无错误地同步我的数据库我猜测它失败了,因为我使用枚举,有人可以指出我正确的方向如何在使用Azure移动应用程序时处理枚举,因为即使我摆脱了脱机支持(sqlLite存储),它仍然失败并且我不断收到错误代码500.

1 个答案:

答案 0 :(得分:1)

根据操作说明,我在我这边检查了这个问题,并在天蓝色门户网站上的快速启动刀片上查看了Download and run the client project和服务器项目。它可以在我的本地工作,你可以参考我的测试如下:

服务器型号:

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
}

客户端型号:

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
}

通过浏览器访问数据:

enter image description here

客户端应用

enter image description here

添加新记录,检查本地sqlite商店:

enter image description here

调用await App.MobileService.SyncContext.PushAsync();,使用fiddler捕获网络跟踪,如下所示:

enter image description here

  

有人可以指出我在使用Azure移动应用程序时如何处理枚举的正确方向,因为即使我摆脱了脱机支持(sqlLite存储)它仍然失败并且我不断收到错误代码500.

在移动应用项目的config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;文件下配置Startup.MobileApp.cs以捕获详细的错误消息。此外,您可以参考here调试移动应用后端。