克隆模式快速与数据库比对数据

                                                                   

一、情景使用

         如果遇到有一批数据要入库,每一条数据入库前都要和数据库现有的数据做比对,以防止数据的重复入库时使用本模式。

二、模式定义和原理

         将数据库中某张表或某批数据完整的加载到内存中,方便程序快速访问该资源,并在资源更新后,保证数据库中的数据和内存中的数据一致性。我们称之为“克隆模式”。

         之所以我称之为克隆模式,是我认为此模式在解决程序快速比对数据库中数据时非常有用,它就像如今基因工程流行的克隆技术一样,将数据库中的某些数据完整的“克隆”到内存中,这样程序就可以只和内存打交道而无需和数据库打交道了。它将程序中需要与数据库中某些数据反复多次比较的数据一次性加载至内存,就能够减少与数据库的交互频率,且需要比对的数据在内存中,因此可以大大提高查找匹配的性能。

         而正确使用这一模式的技术难点就在于如果保证数据库和内存中数据的一致性,避免灾难的发生。

二、模式使用情景

        1、对比数据库中数据不变

         当程序中需要与数据库中某些数据做比较时,而比对的数据是固定。那么就可以在程序启动时一次性加载到内存中,在程序运行期间一直驻留在内存中,不再需要从数据库中反复加载。

        2、对比数据库中数据可变

         在单线程中,程序启动时从数据库克隆欲比对的数据到内存,如果欲入库的比对数据中是不可重复的,那么就可以直接和克隆的数据比对,最后使用批量插入的方法,和数据库交互一次,更新数据库中的数据。然后从数据库中重新克隆一份数据覆盖内存中原来的那份。当然还有一种好方法就是,新数据入库成功后,立即将内存中的那份比对数据也更新,保证和数据库的一致性,从而不必再次与数据库交互克隆一份了。

         在多线程中,问题就会变得麻烦许多。首先还是的保证内存中只有一份克隆的比对数据,只是现在对克隆数据资源的访问和更新操作,都必须要加锁的,否则就是灾难。在程序中只有一处访问和更新克隆资源时,正确的做法就是当一个线程要求和克隆资源访问时,就开始在这段代码加锁直到新数据成功更新至数据库中或确定线程无数据更新为止,且程序重新从数据克隆一份新的至内存,覆盖原来的版本或着跟好的方式是,直接将入库的数据更新至内存,保持与数据库中的一致性,这样可以减少与数据库的交互。

 

        3.入库数据之中具有重复性。

        如果要比对入库的数据都是不同的,那么就可以向2中说的那样完成工作,但如果的相同的,我们必须将每一条将要入库的数据载入到开始从数据库中加载的数据集合中,让后面每一个数据和这个集合做比对,这样就能保证即便新数据中有重复性,也能保证入库后不会出现重复的数据。然后一次性保存新入库的数据,如果更新数据失败,那么就要重新去掉克隆数据中将要入库的数据,或者重新从数据库克隆数据。

       3.使用静态数据集实现共享

       类的静态属性具有当类被加载后,以后对其静态属性的更改将会一直保留下来,任何它的实例对其静态属性的访问都是共享的,如将该类的数据集标记为静态的,就能始终保持该类所有的实例对象都共享同一个数据集属性。甚至您不需要实例该类,直接用类名来调用该静态属性。

      下面是一个多线程下共享数据C#实现, 示例如下:

       1、持久化数据的实体

         public class Site

    {

        private string _name;

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

    }

         2、类的静态数据集属性

    public class SiteStorage

    {

        public static List<Site> ListSite { get; set; }

    }

         3、程序启动时,从数据库中克隆一份数据方法

        private List<Site> LoadAll()

        {

            try

            {

                //从数据库中克隆一份比对数据的代码段

            }

            catch (Exception)

            {

 

                throw;

            }

            return null;

        }

 

          3、数据访问类

    public class SiteDao

    {

        public void DealWhithSite(Site site)

        {

                           //从比对数据开始锁定,直到更新后结束

            lock (typeof (SiteStorage))

            {

                //如果数据库中有这条记录了

                if (FindSite(site) != null)

                {

                    return;

                }

                //如果不存在这条记录,那么就更新到数据库中

                else

                {

                    Save(site);

                    SiteStorage.ListSite.Add(site); //将入库的记录更新至克隆数据中

                }

            }

        }

        private Site FindSite(Site site)

        {

            foreach (var s in SiteStorage.ListSite)

            {

                if (site.Name == s.Name)

                    return s;

            }

            return null;

        }

        private void Save(Site site)

        {

            try

            {

                //更新数据库的代码段

            }

            catch (Exception)

            {               

                throw;

            }           

        }

    }

原文地址:https://www.cnblogs.com/liuche/p/2365914.html