Windows UWP应用使用本地Sqlite和远程Sql(一)

贫猿注册博客园有三年多了,第一次写博客,版式尽量控制的简单点。

本系列文章是简单的记录一下《账簿》本身所运用到的操作本地sqlite和远程sql的代码和结构。

首先的准备工作

安装Sqlite for UWP扩展

从菜单栏找到工具-扩展和更新。在搜索框填写sqlite,在结果里找到“sqlite for Universal App Platform”并安装它。

新建一个8.1的windows 应用,并添加sqlite for windows runtime(8.1)的支持。这时会自动生成SQLiteAsync.cs 和SQLite.cs俩文件,把他们复制到windows10 UWP项目里即。

 

准备解决方案和项目

新建一个通用的空白应用,添加一个名叫Models的文件夹。并为这个项目添加sqlite for Universal App Platform 的引用。

添加一个名叫Services的文件夹,添加现有项SQLiteAsync.cs 和SQLite.cs。

新建一个8.1的windows 应用,并添加sqlite for windows runtime(8.1)的支持。这时会自动生成SQLiteAsync.cs 和SQLite.cs俩文件,把他们复制到windows10 UWP项目里即。

添加BaseModel类。

[DataContract]
    public partial class BaseModel<T> : INotifyPropertyChanged where T : class
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPro(string pName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(pName));
        }

        public static T FromJson(string json)
        {
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                var t = JSON.ReadObject(ms);
                return t as T;
            }
        }
        public override string ToString()
        {
            return ToJson();
        }
        public string ToJson()
        {
            var t = this;
            string json = "";
            using (var ms = new MemoryStream())
            {
                JSON.WriteObject(ms, t);
                var array = ms.ToArray();
                json = Encoding.UTF8.GetString(array, 0, array.Length);
            }
            return json;
        }
        public static DataContractJsonSerializer JSON = new DataContractJsonSerializer(typeof(T));
        [NoRemeberProperty]
        public bool IsSelected
        {
            get
            {
                return _IsSelected;
            }

            set
            {
                _IsSelected = value;
                OnPro("IsSelected");
            }
        }
        [AutoIncrement, PrimaryKey]
        public int ClientId
        {
            get
            {
                return _ClientId;
            }

            set
            {
                _ClientId = value;
            }
        }

        private bool _IsSelected;
        private int _ClientId;
    }
View Code

标记 DataContract 特性是为了日后能将对象序列化为json。

继承 INotifyPropertyChanged 接口是为了能通知UI绑定对象的属性值发生变动。

支持 BaseModel<T> 泛型是为了父类的方法更好的返回子类型。

添加 ClientID 是为以后的子类准备个通用的本地自增长主键,区别于数据库主键。

标记 NoRemeberProperty 特性是为了让 本地sqlite在生成类型的map时略过一些不必要存储的属性。

 public class NoRemeberProperty : Attribute
    {

    }
View Code

添加UsercAccount类。

[DataContract]
    public class UserAccount : BaseModel<UserAccount>
    {
        private string _Name;
        private string _Email;
        private string _Password;

        [DataMember]
        public string Name
        {
            get
            {
                return _Name;
            }

            set
            {
                _Name = value; OnPro("Name");
            }
        }
        [DataMember]
        public string Email
        {
            get
            {
                return _Email;
            }

            set
            {
                _Email = value; OnPro("Email");
            }
        }
        [DataMember]
        public string Password
        {
            get
            {
                return _Password;
            }

            set
            {
                _Password = value; OnPro("Password");
            }
        }
    }
View Code

标记 DataMember 特性是为了日后能将属性序列化为json。

集成 BaseModel 类是为了能省化部分代码。

添加Sss类到Services文件夹

public async static void InitDataBase()
        {
            bool isNeedCreate = false;
            StorageFile sf = null;
            try
            {
                sf = await StorageFile.GetFileFromPathAsync(DBPath);
            }
            catch (FileNotFoundException ex) //文件不存在
            {
                isNeedCreate = true;
            }
            if (isNeedCreate)
            {
                try
                {
                    Setting.Values.Clear();
                    var db = new SQLiteAsyncConnection(DBPath);
                    await db.CreateTableAsync<RoundTask>();
                    await db.CreateTableAsync<AssetChanges>();
                    await db.CreateTableAsync<UserAccount>();
                    await db.CreateTableAsync<MoneyInfo>();
                }
                catch (Exception er) //试图加载格式不正确的程序
                {
                    sf.DeleteAsync();
                    OnException("初始化数据库失败", er);
                    Sss.WriteException("sss.initdatebase", er);
                }
            }
        }
View Code
public static string DBPath
        {
            get
            {
                //return "connectionDrive.sqlite";
                return System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "connectionDrive.sqlite");
            }
        }
View Code

并添加一个用于初始化数据库的静态方法,将其放置于app.xaml.cs 里的第53行,OnLaunched方法中。

--代码弄错了,多创建了几个表,请删除。

添加StatusCode枚举

[DataContract]
    public enum StatusCode
    {
        /// <summary>
        /// 账户不存在
        /// </summary>
        [EnumMember]
        UserAccount_NotExists,
        /// <summary>
        /// 密码错误
        /// </summary>
        [EnumMember]
        Password_Error,
        /// <summary>
        /// 用户账户已存在
        /// </summary>
        [EnumMember]
        UserAccount_Exists,
        /// <summary>
        /// 网络错误致使数据传输出错或失败
        /// </summary>
        [EnumMember]
        Network_Error,
        /// <summary>
        /// 未初始化请求
        /// </summary>
        [EnumMember]
        None,
        /// <summary>
        /// 已成功提交并执行请求
        /// </summary>
        [EnumMember]
        Completed,
        /// <summary>
        /// 操作失败
        /// </summary>
        [EnumMember]
        Error,
        /// <summary>
        /// 已停止支持该版本,请更新你的程序
        /// </summary>
        [EnumMember]
        Application_Stop,
    }
View Code

 

标记 EnumMember 特性是为了让枚举能够序列化为json。

添加Local类到Services 文件夹

public static SQLiteAsyncConnection db = new SQLiteAsyncConnection(Sss.DBPath);
        public static async Task<StatusCode> AddObject(object obj)
        {
            try
            {
                await db.InsertAsync(obj);
                OnAddedObject(obj);
                return StatusCode.Completed;
            }
            catch (Exception e)
            {
                Sss.WriteException("local.addobject", e);
                return StatusCode.Error;
            }
        }

        public static async Task<StatusCode> UpdateObject(object obj)
        {
            try
            {
                await db.UpdateAsync(obj);
                OnUpdatedObject(obj);
                return StatusCode.Completed;
            }
            catch (Exception e)
            {
                Sss.WriteException("local.updateobject", e);
                return StatusCode.Error;
            }
        }
View Code

 

并添加一个用于添加和更新数据的静态方法。

public static async Task<List<string>> GetEmails()
        {
            try
            {
                var sql = "select * from UserAccount";
                var rs = await db.QueryAsync<UserAccount>(sql);
                return rs.Select(c => c.Email).ToList();
            }
            catch (Exception e)
            {
                return null;
            }
        }

        public static async Task<bool> CanLogin(string email, string pwd)
        {
            try
            {
                var sql = "select * from UserAccount where email = '" + email + "' and password = '" + pwd + "'";
                var rs = await db.QueryAsync<UserAccount>(sql);
                return rs.Count == 1;
            }
            catch (Exception e)
            {
                return false;
            }
        }
View Code

添加一个业务逻辑的代码。

添加WB类到Services文件夹

[DataContract]
    public enum UserWork
    {
        [EnumMember]
        Login,
}

public enum WorkStatus
    {
        PostBegin,
        PostEnd,
        PostPause
    }
View Code
 [DataContract]
    public class HR
    {
        private Dictionary<string, object> Values = new Dictionary<string, object>();
        [DataMember]
        public string Source
        {
            get
            {
                var s = "";
                foreach (var t in Values)
                {
                    s += t.Key + "=" + t.Value + "&";
                }
                if (s.EndsWith("&"))
                {
                    s = s.Substring(0, s.Length - 1);
                }
                return s;
            }
            set
            {
                Values.Clear();
                foreach (var t in value.Split('&'))
                {
                    var s = t.Split('=');
                    Values.Add(s[0], s[1]);
                }
            }
        }

        public StatusCode Status
        {
            get
            {
                if (this.Values.ContainsKey("Status"))
                    return (StatusCode)Enum.Parse(typeof(StatusCode), this["Status"].ToString());
                else
                    return StatusCode.None;
            }
            set { this["Status"] = value.ToString(); }
        }

        public object this[string key]
        {
            get
            {
                if (this.Values.ContainsKey(key))
                    return this.Values[key];
                else
                    return string.Empty;
            }
            set
            {
                if (!this.Values.ContainsKey(key))
                    this.Values.Add(key, String.Empty);
                this.Values[key] = value;
            }
        }
        public T Get<T>(string key) where T : class
        {
            return this.Values[key] as T;
        }
    }
View Code

 

private static string _workUri = "http://localhost:9009/work.ashx";
        private static string _version = "1";
        public static event EventHandler<WorkStatus> WorkStatusChanged;

        public static string Version
        {
            get { return WB._version; }
            set { WB._version = value; }
        }
        public static string WorkUri
        {
            get
            {
                if (Sss.WorkUir != null)
                    _workUri = Sss.WorkUir;
                return _workUri;
            }
            set
            {
                _workUri = value;
                Sss.WorkUir = _workUri;
            }
        }

        private static void OnWorkStatusChanged(UserWork work, WorkStatus status)
        {
            if (WorkStatusChanged != null)
            {
                WorkStatusChanged(work, status);
            }
        }
        private async static Task<String> Post(string uri, HttpFormUrlEncodedContent args)
        {
            HttpClient hc = new HttpClient();
            var r = await hc.PostAsync(new Uri(WorkUri), args) as HttpResponseMessage;
            return await r.Content.ReadAsStringAsync();
        }


        public async static Task<HR> Post(UserWork type, params object[] args)
        {
            HR hr = null;
            try
            {
                OnWorkStatusChanged(type, WorkStatus.PostBegin);
                var pd = GetData(type, args);
                hr = new HR() { Source = await Post(WorkUri, GetData(type, args)) };
                return hr;
            }
            catch (Exception er)
            {
                return new HR() { Status = StatusCode.Network_Error };
            }
            finally
            {
                //if (hr["msg"].ToString().Length > 0)
                //    await Sss.Show("", hr["msg"].ToString(), Sss.OkCmd);
                OnWorkStatusChanged(type, WorkStatus.PostEnd);
            }
        }

        public static HttpFormUrlEncodedContent GetData(UserWork type, params object[] args)
        {
            var lst = new List<KeyValuePair<string, string>>();
            lst.Add(new KeyValuePair<string, string>("type", type.ToString()));
            lst.Add(new KeyValuePair<string, string>("version", Version.ToString()));
            if (type == UserWork.Login)
            {
                lst.Add(new KeyValuePair<string, string>("UserAccount", args.Where(c => c is UserAccount).First().ToString()));
            }
            return new HttpFormUrlEncodedContent(lst);
         }
public static string GetStatusText(UserWork type)
        {
            string status = "";
            switch (type)
            {
                case UserWork.Login:
                    status += "正在登录";
                    break;
             }
     return status + "..." ;
}
View Code

 

 添加 请求方法。

        public bool 是否有网 { get; set; }
        private async void button_Click(object sender, RoutedEventArgs e)
        {
            if (是否有网)
            {
                var hr = await WB.Post(UserWork.Login, new UserAccount() { Email = txtEmail.Text, Password = pwd.Password }); 
                if (hr.Status == StatusCode.Completed)
                {
                    //登录成功;
                }
            }
            else
            {
                if (Local.CanLogin(txtEmail.Text, pwd.Password))
                {
                    //登录成功;
                }
            }
        }
View Code

登录按钮

网页Ashx文件的处理代码

public void ProcessRequest(HttpContext context)
        {
            var h = new HR();
            h.Status = StatusCode.None;
            try
            {
var type = (UserWork)Enum.Parse(typeof(UserWork), context.Request["type"]);
switch (type)
            {
                case UserWork.Login:
                   Login(context, h);
                    break;
}
              }
            catch (Exception e)
            {
                h.Status = StatusCode.Error;
                h["msg"] = e.Message + (e.InnerException == null ? "" : e.InnerException.Message);
            }
            finally            {
                context.Response.Write(h.Source);
                context.Response.End();
            }
        }

private static StatusCode Login(HttpContext context, HR h)
        {
            var ut = Sss.FromJson<UserAccount>(context.Request["UserAccount"]);
            if (udao.IsExists(ut.Email))
            {
                if (udao.Login(ut))
                {
                    h.Status = StatusCode.Completed;

                    h["UserAccount"] = ut.ToString();
                }
                else
                {
                   h.Status = StatusCode.Password_Error;
                }
            }
            else
            {
                h.Status = StatusCode.UserAccount_NotExists;
            }
        }
View Code

 

 

终于写完了,不知道合不合适,先发出来看看。

 

posted @ 2015-12-02 21:26  蓝多  阅读(1303)  评论(2编辑  收藏  举报