WebForm —— 页面状态自动加载和保存(下)

很久之前写完了上、中两篇,因为各种原因吧,到现在也没有完成下篇,心里一直有些愧疚。好了,废话不说了,把下篇补上,也是我用到现在的代码。

 

第一步,新建一个类,并且让类从 BasePage 继承。

第二步,重写 BasePage 类的两个虚方法:GetCacheData 和 SaveCacheData ,分别处理数据的 Load 和 Save 。

第三步,保存这个类,并让页面的后台类(系统默认继承自 Page)继承自这个新类就可以了。

 

好了,步骤理解之后,原理在上中两篇说的差不多了,剩下的看代码就行了,有问题给我留言就 OK 。

 

首先是中篇中提到的的 AutoSaveAttribute 特性类:

using System;

using System.Diagnostics;



namespace Lenic.Web

{

    /// <summary>

    /// 自动保存属性,配合 BasePage 能够实现 Web 页面后台代码类字段或属性的自动保存和加载。

    /// </summary>

    [DebuggerStepThrough]

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]

    public class AutoSaveAttribute : Attribute

    {

        /// <summary>

        /// 初始化创建一个 <see cref="AutoSaveAttribute"/> 类的实例,使得具有该属性的类的属性或字段具有自动保存的特性。

        /// </summary>

        public AutoSaveAttribute() { }

    }

}

然后是核心处理逻辑 BasePage 虚基类:

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Reflection;

using System.Web.UI;



namespace Lenic.Web

{

    /// <summary>

    /// 提供了 Web 页面自动保存属性处理的基类

    /// </summary>

    [DebuggerStepThrough]

    public abstract class BasePage : Page

    {

        #region Reload Fields And Properties

        /// <summary>

        /// 引发 <see cref="E:System.Web.UI.Control.Load"/> 事件。

        /// </summary>

        /// <param name="e">包含事件数据的 <see cref="T:System.EventArgs"/> 对象。</param>

        protected override void OnLoad(EventArgs e)

        {

            // 初始化当前用户控件的缓冲字典

            InitCacheDic();



            if (Page.IsPostBack)

            {

                // 获得缓冲数据列表

                var list = GetCacheData();



                // 自动加载 AutoSave 属性保存的值

                int index = 0;

                foreach (MemberInfo info in CacheDic[CurrType])

                {

                    if (info.MemberType == MemberTypes.Property)

                    {

                        PropertyInfo pi = info as PropertyInfo;

                        object value = list[index];

                        if (value != null)

                            pi.SetValue(this, value, null);

                    }

                    else if (info.MemberType == MemberTypes.Field)

                    {

                        FieldInfo fi = info as FieldInfo;

                        object value = list[index];

                        fi.SetValue(this, value);

                    }

                    index++;

                }

            }

            base.OnLoad(e);

        }

        #endregion



        #region Save Fields And Properties

        /// <summary>

        /// 在这里实现属性的自动保存。

        /// </summary>

        protected override object SaveViewState()

        {

            // 初始化当前用户控件的缓冲字典

            InitCacheDic();



            // 初始化要保存的属性值列表

            List<object> list = new List<object>();

            foreach (MemberInfo info in CacheDic[CurrType])

            {

                if (info.MemberType == MemberTypes.Property)

                {

                    PropertyInfo pi = info as PropertyInfo;

                    list.Add(pi.GetValue(this, null));

                }

                else if (info.MemberType == MemberTypes.Field)

                {

                    FieldInfo fi = info as FieldInfo;

                    list.Add(fi.GetValue(this));

                }

            }



            // 保存更改

            SaveCacheData(list);



            return base.SaveViewState();

        }

        #endregion



        #region Business Properties

        /// <summary>

        /// 用户控件类型及自动保存属性成员缓冲字典

        /// </summary>

        protected static Dictionary<Type, MemberInfo[]> CacheDic = null;



        /// <summary>

        /// 当前页面的类型

        /// </summary>

        protected Type CurrType = null;



        /// <summary>

        /// 获得成员列表的绑定标识.

        /// </summary>

        private static readonly BindingFlags Flag;



        /// <summary>

        /// 初始化 <see cref="BasePage"/> 类.

        /// </summary>

        static BasePage()

        {

            CacheDic = new Dictionary<Type, MemberInfo[]>();



            Flag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy;

        }



        /// <summary>

        /// 初始化当前页面的缓冲字典

        /// </summary>

        private void InitCacheDic()

        {

            // 获得当前实例类型

            CurrType = GetType();



            MemberInfo[] mems = null;

            if (!CacheDic.TryGetValue(CurrType, out mems))

            {

                var list = CurrType.GetMembers(Flag)

                    .Where(p => Attribute.IsDefined(p, typeof(AutoSaveAttribute), false))

                    .ToArray();

                CacheDic[CurrType] = list;

            }

        }

        #endregion



        #region Data Fetch

        /// <summary>

        /// 获得缓存的数据。

        /// </summary>

        /// <returns>重获的数据。</returns>

        protected abstract List<object> GetCacheData();



        /// <summary>

        /// 保存需要缓存的数据。

        /// </summary>

        /// <param name="data">需要保存的数据数组。</param>

        protected abstract void SaveCacheData(List<object> data);

        #endregion

    }

}

其次是对 GetCacheData 方法和 SaveCacheData 的实现:

private ICacheList _currCache = null;

private ICacheList CurrCache

{

    get

    {

        if (_currCache == null)

        {

            _currCache = SqliteCacheList.NewInstance(CurrUser.SessionID, CurrUser.ID, CurrType.FullName);

            _currCache.LoadPageData();

        }

        return _currCache;

    }

}



protected override List<object> GetCacheData()

{

    var data = CurrCache.Where(p => p.PageID == CurrType.FullName)

        .Select(p => p.Data == null ? null : p.Data.DeserializeFromByte<object>())

        .ToList();



    return data;

}



protected override void SaveCacheData(List<object> data)

{

    data.ForEach((p, i) => CurrCache[i].Data = p == null ? null : p.SerializeToByte());



    CurrCache.Save();

}

这里用到了一些自定义的扩展方法:

List<T> 类的 ForEach 方法添加了第二个参数 i 表示当前索引值。

DeserializeFromByte<T> 是 byte[] 字节数组反序列化为 T 类型对象的扩展。

SerializeToByte 是将当前对象序列化为 byte[] 字节数组的扩展。

 

这三个方法应该问题都不大,百度一下就能找到类似的实现,这里就不再贴代码了。

 

再次是缓存的具体实现代码。下面的代码是我个人实现的方法,每个人的想法可能都不同,权当抛砖引玉了:

观察仔细的童鞋,可以看到 ICacheList 接口,这就是我自定义的一个接口:

using System.Collections.Generic;



namespace Lenic.Web.Caches

{

    /// <summary>

    /// 缓存列表

    /// </summary>

    public interface ICacheList : IEnumerable<CacheItem>

    {

        /// <summary>

        /// 【自动新建】获得或设置缓存项。

        /// </summary>

        /// <param name="i">项的索引</param>

        /// <returns>缓存项</returns>

        CacheItem this[int i] { get; set; }

        /// <summary>

        /// 从数据库中加载数据

        /// </summary>

        /// <typeparam name="T">数据的类型</typeparam>

        /// <param name="dataId">数据标识</param>

        /// <returns>还原的原始数据</returns>

        T LoadData<T>(string dataId);

        /// <summary>

        /// 从数据库中加载页面数据

        /// </summary>

        /// <returns>加载后的列表</returns>

        ICacheList LoadPageData();

        /// <summary>

        /// 持久化数据变化

        /// </summary>

        void Save();

    }

}

其中 IEnumerable<CacheItem> 中的 CacheItem 表示缓存项的虚基类:

using System;

using System.Diagnostics;



using Lenic.Data;

using Lenic.Extensions;



namespace Lenic.Web.Caches

{

    /// <summary>

    /// 缓存项

    /// </summary>

    [Serializable]

    [DebuggerStepThrough]

    public abstract class CacheItem

    {

        #region Instance

        /// <summary>

        /// 初始化创建一个 <paramref name="CacheItem"/> 类的对象。

        /// </summary>

        public CacheItem()

        {

            MarkNew();

        }



        /// <summary>

        /// 初始化创建一个 <paramref name="CacheItem"/> 类的对象。

        /// </summary>

        /// <param name="isFetched"><c>true</c> 表示是从数据库中填充获得的; 否则返回 <c>false</c> </param>

        public CacheItem(bool isFetched)

        {

            if (isFetched)

                MarkFetched();

            else

                MarkNew();

        }



        /// <summary>

        /// 初始化创建一个 <paramref name="CacheItem"/> 类的对象。

        /// </summary>

        /// <param name="sessionID">会话标识</param>

        /// <param name="userID">用户标识</param>

        /// <param name="pageID">页面标识</param>

        /// <param name="dataID">数据标识</param>

        /// <returns>获得或新建的一个 <paramref name="CacheItem"/> 类的对象</returns>

        public CacheItem(string sessionID, string userID, string pageID, string dataID)

            : this()

        {

            SessionID = sessionID;

            UserID = userID;

            PageID = pageID;

            DataID = dataID;

        }

        #endregion



        #region Business Properties

        /// <summary>

        /// 获得或设置当前会话标识。

        /// </summary>

        public string SessionID { get; set; }

        /// <summary>

        /// 获得当前用户标识。

        /// </summary>

        public string UserID { get; set; }

        /// <summary>

        /// 获得或设置当前页面标识。

        /// </summary>

        public string PageID { get; set; }

        /// <summary>

        /// 获得或设置当前数据标识。

        /// </summary>

        public string DataID { get; set; }



        private byte[] _data = null;

        /// <summary>

        /// 获得或设置当前数据对象数据。

        /// </summary>

        public byte[] Data

        {

            get { return _data; }

            set

            {

                _data = value;

                IsDirty = true;

            }

        }



        /// <summary>

        /// 获得最近一次的修改时间

        /// </summary>

        public DateTime LastChanged { get; set; }



        /// <summary>

        /// 获得当前数据对象。

        /// </summary>

        public object DataObject

        {

            get { return Data == null ? null : Data.DeserializeFromByte<object>(); }

        }

        #endregion



        #region Mark Instance

        /// <summary>

        /// 获得当前实例是否是新建、未保存到数据库中。

        /// </summary>

        public bool IsNew { get; protected set; }



        /// <summary>

        /// 获得当前实例是否是否是从数据库中检索并填充的。

        /// </summary>

        public bool IsFetched { get; protected set; }



        /// <summary>

        /// 获得一个值, 通过该值指示当前实例对象是否被修改过。

        /// </summary>

        /// <value><c>true</c> 表示被修改过; 否则返回 <c>false</c> </value>

        public bool IsDirty { get; protected set; }



        /// <summary>

        /// 获得当前实例是否已经标识为删除。

        /// </summary>

        public bool IsDeleted { get; protected set; }



        /// <summary>

        /// 标识当前对象是新建、未保存到数据库中。

        /// </summary>

        /// <returns>更改后的自身。</returns>

        public CacheItem MarkNew()

        {

            IsDirty = false;

            IsNew = true;

            IsFetched = false;

            IsDeleted = false;

            return this;

        }

        /// <summary>

        /// 标识当前对象为从数据库中检索并填充的。

        /// </summary>

        /// <returns>更新后的自身。</returns>

        public CacheItem MarkFetched()

        {

            IsDirty = false;

            IsNew = false;

            IsFetched = true;

            IsDeleted = false;

            return this;

        }

        /// <summary>

        /// 标识当前实例对象需要在保存时删除。

        /// </summary>

        /// <returns>修改后的自身。</returns>

        public CacheItem MarkDeleted()

        {

            IsDirty = true;

            IsDeleted = true;

            return this;

        }

        #endregion



        #region Equal

        public override bool Equals(object obj)

        {

            if (obj == null || typeof(CacheItem) != obj.GetType())

                return false;



            var target = obj as CacheItem;

            if (this.SessionID == target.SessionID &&

                this.UserID == target.UserID &&

                this.PageID == target.PageID &&

                this.DataID == target.DataID)

                return true;



            return base.Equals(obj);

        }



        public override int GetHashCode()

        {

            int hash = SessionID.GetHashCode();

            hash ^= UserID.GetHashCode();

            hash ^= PageID.GetHashCode();

            hash ^= DataID.GetHashCode();



            return hash;

        }

        #endregion



        #region Data Operater

        /// <summary>

        /// 持久化到数据库中。

        /// </summary>

        /// <param name="t">数据库操作实例对象</param>

        /// <returns>影响的行数。</returns>

        public abstract int Save(IDataAccesser t);

        #endregion

    }

}

在项目中我用 Sqlite 写了一个实现,具体代码如下:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Diagnostics;

using Lenic.Data;

using Lenic.Data.Extensions;

using System.Linq;



using Lenic.Extensions;



namespace Lenic.Web.Caches.Sqlite

{

    /// <summary>

    /// 页面 ViewState 数据库缓冲

    /// </summary>

    [Serializable]

    [DebuggerStepThrough]

    public class SqliteCacheList : ICacheList

    {

        private List<SqliteCacheItem> list = new List<SqliteCacheItem>();



        #region DbHelper

        /// <summary>

        /// 缓存数据库连接字符串

        /// </summary>

        public static string ConnectionString = @"Data Source=|DataDirectory|\PageCache.dll";



        /// <summary>

        /// 数据库访问实例对象

        /// </summary>

        private static IDataAccesser DB = new DbHelper(DbProviders.SQLiteProvider, ConnectionString);



        /// <summary>

        /// 查询缓冲表是否在数据库中存在, 返回一个 <paramref name="System.Int64"/> 类型的值表示找到的个数.

        /// </summary>

        private const string SelectExists = "SELECT COUNT(*) AS COUNTS FROM SQLITE_MASTER WHERE TYPE = 'table' AND NAME = 'TB_Page'";



        /// <summary>

        /// 创建缓冲表语句.

        /// </summary>

        private const string CreateTable = @"CREATE TABLE [TB_Page] (

                                                 [SessionID] nvarchar(50) NOT NULL,

                                                 [UserID] nvarchar(50) NOT NULL,

                                                 [PageID] nvarchar(50) NOT NULL,

                                                 [DataID] nvarchar(50) NOT NULL,

                                                 [Data] blob,

                                                 [LastChanged] timestamp NOT NULL

                                             )";



        /// <summary>

        /// 删除缓冲表语句.

        /// </summary>

        private const string DropTable = "Drop Table TB_Page";



        /// <summary>

        /// 收缩数据库语句.

        /// </summary>

        private const string ShrinkDB = "Vacuum";



        /// <summary>

        /// 清除用户之前的记录文本.

        /// </summary>

        private const string ClearPreviousText = "DELETE FROM [TB_Page] WHERE [UserID] = '{0}'";



        /// <summary>

        /// 清除指定 SessionID 指定用户的的记录文本.

        /// </summary>

        private const string ClearSessionText = "DELETE FROM [TB_Page] WHERE [SessionID] = {0} AND [UserID] = '{1}'";



        /// <summary>

        /// 【页面缓存】0 = 会话标识 AND 1 = 用户标识 AND 2 = 页面标识

        /// </summary>

        private const string SelectPageSql = "SELECT * FROM [TB_Page] WHERE [SessionID] = '{0}' AND [UserID] = '{1}' AND [PageID] = '{2}'";



        /// <summary>

        /// 【变量数据】0 = 会话标识 AND 1 = 用户标识 AND 2 = 页面标识 AND 3 = 数据标识

        /// </summary>

        private const string SelectSingleDataSql = "SELECT [Data] FROM [TB_Page] WHERE [SessionID] = '{0}' AND [UserID] = '{1}' AND [PageID] = '{2}' AND [DataID] = '{3}'";

        #endregion



        #region Business Properties

        /// <summary>

        /// 获得会话标识

        /// </summary>

        public string SessionID { get; private set; }

        /// <summary>

        /// 获得用户标识

        /// </summary>

        public string UserID { get; private set; }

        /// <summary>

        /// 获得页面标识

        /// </summary>

        public string PageID { get; private set; }

        #endregion



        #region New Instance

        private SqliteCacheList() { }

        /// <summary>

        /// 新建一个列表对象

        /// </summary>

        public static SqliteCacheList NewInstance(string sessionID, string userID, string pageID)

        {

            return new SqliteCacheList

            {

                SessionID = sessionID,

                UserID = userID,

                PageID = pageID,

            };

        }



        /// <summary>

        /// 【自动新建】获得或设置缓存项。

        /// </summary>

        /// <value></value>

        /// <returns>缓存项</returns>

        public CacheItem this[int i]

        {

            get

            {

                var item = list.ElementAtOrDefault(i);

                if (item == null)

                {

                    item = new SqliteCacheItem(SessionID, UserID, PageID, i.ToString());

                    list.Add(item);

                }

                return item;

            }

            set

            {

                if (i >= list.Count)

                    list.Add((SqliteCacheItem)value);

                else

                {

                    list.RemoveAt(i);

                    list.Insert(i, (SqliteCacheItem)value);

                }

            }

        }

        #endregion



        #region IEnumerable 成员

        /// <summary>

        /// 返回一个循环访问集合的枚举数。

        /// </summary>

        /// <returns>可用于循环访问集合的 System.Collections.Generic.IEnumeratorlt;SqliteCacheItemgt;。</returns>

        public IEnumerator<CacheItem> GetEnumerator()

        {

            var data = list.GetEnumerator();

            while (data.MoveNext())

            {

                yield return (CacheItem)data.Current;

            }

        }



        /// <summary>

        /// 返回一个循环访问集合的枚举数。

        /// </summary>

        /// <returns>可用于循环访问集合的 System.Collections.Generic.IEnumeratorlt;SqliteCacheItemgt;。</returns>

        IEnumerator<CacheItem> IEnumerable<CacheItem>.GetEnumerator()

        {

            return this.GetEnumerator();

        }



        /// <summary>

        /// 返回一个循环访问集合的枚举数。

        /// </summary>

        /// <returns>可用于循环访问集合的 System.Collections.IEnumerator。</returns>

        IEnumerator IEnumerable.GetEnumerator()

        {

            return this.GetEnumerator();

        }

        #endregion



        #region Data Operater

        /// <summary>

        /// 初始化缓冲数据库。

        /// </summary>

        /// <param name="deleteTable">如果设置为 <c>true</c> 标识先删除 Table 再重建。</param>

        public static void Init(bool deleteTable)

        {

            long count = 0;

            using (DataReaderEx con = DB.Read(SelectExists))

            {

                count = con.Field<long>("COUNTS");

            }



            if (count > 0 && deleteTable)

                DB.Write(DropTable);

            if (count == 0)

                DB.Write(CreateTable);

            DB.Write(ShrinkDB);

        }



        /// <summary>

        /// 从数据库中清除用户旧的记录, 立即生效!

        /// </summary>

        /// <param name="userID">用户标识.</param>

        public static void ClearPrevious(string userId)

        {

            DB.Write(ClearPreviousText.With(userId));

        }



        /// <summary>

        /// 持久化数据变化

        /// </summary>

        public void Save()

        {

            using (var con = DbProviders.SQLiteProvider.CreateConnection())

            {

                con.ConnectionString = ConnectionString;

                con.Open();

                var transaction = con.BeginTransaction();



                var t = new TransactionHelper(transaction);

                try

                {

                    foreach (var item in this)

                    {

                        int count = item.Save(t);

                        if (count == 0)

                            throw new DatabaseException("数据库操作失败");

                    }

                    t.Commit();

                }

                catch (Exception e)

                {

                    t.Rollback();

                    throw e;

                }

            }

        }



        /// <summary>

        /// 从数据库中加载页面数据

        /// </summary>

        /// <param name="sessionId">会话标识</param>

        /// <param name="userId">用户标识</param>

        /// <param name="pageId">页面标识</param>

        /// <returns>加载后的列表</returns>

        public ICacheList LoadPageData()

        {

            if (SessionID.IsNullOrEmptyTrim())

                throw new ApplicationException("会话标识不能为空");

            if (UserID.IsNullOrEmptyTrim())

                throw new ApplicationException("用户标识不能为空");

            if (PageID.IsNullOrEmptyTrim())

                throw new ApplicationException("页面标识不能为空");



            using (var con = DbProviders.SQLiteProvider.CreateConnection())

            {

                con.ConnectionString = ConnectionString;

                con.Open();

                var transaction = con.BeginTransaction();



                var t = new TransactionHelper(transaction);

                try

                {

                    using (DataReaderEx dr = t.Read(SelectPageSql.With(SessionID, UserID, PageID)))

                    {

                        list = dr.ToList<SqliteCacheItem>(p => new SqliteCacheItem(true)

                        {

                            SessionID = p.Field<string>("SessionID"),

                            UserID = p.Field<string>("UserID"),

                            PageID = p.Field<string>("PageID"),

                            DataID = p.Field<string>("DataID"),

                            Data = p.Field<byte[]>("Data"),

                            LastChanged = p.Field<DateTime>("LastChanged"),

                        });

                    }

                }

                finally

                {

                    t.Rollback();

                }

            }

            return this;

        }



        /// <summary>

        /// 从数据库中加载数据

        /// </summary>

        /// <typeparam name="T">数据的类型</typeparam>

        /// <param name="sessionId">会话标识</param>

        /// <param name="userId">用户标识</param>

        /// <param name="dataId">数据标识</param>

        /// <returns>还原的原始数据</returns>

        public T LoadData<T>(string dataId)

        {

            if (SessionID.IsNullOrEmptyTrim())

                throw new ApplicationException("会话标识不能为空");

            if (UserID.IsNullOrEmptyTrim())

                throw new ApplicationException("用户标识不能为空");



            var data = DB.GetValue(SelectSingleDataSql.With(SessionID, UserID, "Lenic.Global", dataId))

                         .DirectTo<byte[]>();



            if (data == null) return default(T);

            return data.DeserializeFromByte<T>();

        }

        #endregion

    }

}

下面是缓存项的实现类:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Diagnostics;

using Lenic.Data;

using Lenic.Extensions;



namespace Lenic.Web.Caches.Sqlite

{

    /// <summary>

    /// Sqlite 缓存项

    /// </summary>

    [Serializable]

    [DebuggerStepThrough]

    public class SqliteCacheItem : CacheItem

    {

        #region Instance

        /// <summary>

        /// 初始化创建一个 <paramref name="SqliteCacheItem"/> 类的对象。

        /// </summary>

        public SqliteCacheItem()

        {

            MarkNew();

        }



        /// <summary>

        /// 初始化创建一个 <paramref name="SqliteCacheItem"/> 类的对象。

        /// </summary>

        /// <param name="isFetched"><c>true</c> 表示是从数据库中填充获得的; 否则返回 <c>false</c> </param>

        public SqliteCacheItem(bool isFetched)

        {

            if (isFetched)

                MarkFetched();

            else

                MarkNew();

        }



        /// <summary>

        /// 初始化创建一个 <paramref name="SqliteCacheItem"/> 类的对象。

        /// </summary>

        /// <param name="sessionID">会话标识</param>

        /// <param name="userID">用户标识</param>

        /// <param name="pageID">页面标识</param>

        /// <param name="dataID">数据标识</param>

        /// <returns>获得或新建的一个 <paramref name="SqliteCacheItem"/> 类的对象</returns>

        public SqliteCacheItem(string sessionID, string userID, string pageID, string dataID)

            : this()

        {

            SessionID = sessionID;

            UserID = userID;

            PageID = pageID;

            DataID = dataID;

        }

        #endregion



        #region Command Text

        /// <summary>

        /// 【插入】0 = 会话标识 AND 1 = 用户标识 AND 2 = 页面标识 AND 3 = 数据标识 AND 4 = 插入序号

        /// </summary>

        internal const string InsertText = "INSERT INTO [TB_Page]([SessionID], [UserID], [PageID], [DataID], [Data], [LastChanged]) Values('{0}', '{1}', '{2}', '{3}', @p{4}, datetime());";

        /// <summary>

        /// 【更新】0 = 会话标识 AND 1 = 用户标识 AND 2 = 页面标识 AND 3 = 数据标识 AND 4 = 更新序号

        /// </summary>

        internal const string UpdateText = "UPDATE [TB_Page] SET [Data] = @p{4}, [LastChanged] = datetime() WHERE [SessionID] = '{0}' AND [UserID] = '{1}' AND [PageID] = '{2}' AND [DataID] = '{3}'";

        /// <summary>

        /// 【删除】0 = 会话标识 AND 1 = 用户标识 AND 2 = 页面标识 AND 3 = 数据标识

        /// </summary>

        internal const string DeleteText = "Delete From [TB_Page] WHERE [SessionID] = '{0}' AND [UserID] = '{1}' AND [PageID] = '{2}' AND [DataID] = '{3}'";

        #endregion



        #region Data Operater

        /// <summary>

        /// 持久化到数据库中。

        /// </summary>

        /// <param name="t">数据库操作实例对象</param>

        /// <returns>影响的行数。</returns>

        public override int Save(IDataAccesser t)

        {

            if (IsNew && IsDeleted) return -1;

            if (!IsDirty) return -1;

            if (IsDeleted) return t.WriteD(DeleteText.With(SessionID, UserID, PageID, DataID));

            if (IsNew) return t.WriteD(InsertText.With(SessionID, UserID, PageID, DataID, 0), Data);

            if (IsFetched) return t.WriteD(UpdateText.With(SessionID, UserID, PageID, DataID, 0), Data);



            return 0;

        }

        #endregion

    }

}

就到这里吧,能拿出来的都拿出来了。后面的代码也包含了一些自定义方法,我略作解释:

IDataAccesser 接口操作数据库,包含下面的方法,具体靠 DbHelper 和 TransactionHelper 实现,我就不写了,你应该能写出来一个实现类。很简单的!

/// <summary>

/// 数据库操作接口

/// </summary>

public interface IDataAccesser

{

    /// <summary>

    /// 创建一个新的数据库命令对象。

    /// </summary>

    /// <returns>一个新的数据库命令对象。</returns>

    DbCommand NewCommand();

    /// <summary>

    /// 执行查询, 并返回查询所返回的结果集中第一行的第一列. 所有其他的列和行将被忽略.

    /// </summary>

    /// <param name="cmd">查询命令实例对象.</param>

    /// <returns>结果集中第一行的第一列.</returns>

    object GetValue(DbCommand cmd);

    /// <summary>

    /// 从数据库中查询并返回结果集(DataSet 类型)。

    /// </summary>

    /// <param name="cmd">查询命令实例对象。</param>

    /// <returns>查询结果集。</returns>

    DataSet Query(DbCommand cmd);

    /// <summary>

    /// 从数据库中查询并返回一个 <paramref name="System.Data.Common.DbDataReader"/> 类型的实例对象。

    /// </summary>

    /// <param name="cmd">查询命令实例对象。</param>

    /// <returns>查询结果集。</returns>

    DbDataReader Read(DbCommand cmd);

    /// <summary>

    /// 执行数据库操作, 并返回影响的行数。

    /// </summary>

    /// <param name="cmd">执行命令实例对象。</param>

    /// <returns>影响的行数。</returns>

    int Write(DbCommand cmd);

}

DataReaderEx 是 DbDataReader 的一个实现类,用修饰模式实现,这里你可以把其当成 IDataReader 接口来看待。

IsNullOrEmptyTrim 是对 String 类 IsNullOrEmpty 方法的封装,同时增加了对 Trim 方法处理后的判断。

DirectTo 是对类型强转的包装,等于 (T)obj 。

With 是对 String.Format 的封装。

你可能感兴趣的:(webform)