public void Put(string resourceKind, SyncDigestEntryInfo info)
        {
            if (null == resourceKind)
                throw new ArgumentNullException("resourceKind");
            if (resourceKind == String.Empty)
                throw new ArgumentException("Parameter value is empty.", "resourceKind");

            if (null == info)
                throw new ArgumentNullException("info");

            // TODO: Validate entry property values

            // We set the priority on 'update'.
            lock (lockObj)
            {
                try
                {
                    _provider.Update(resourceKind, info);
                }
                catch (StoreException)
                {
                    _provider.Add(resourceKind, info);
                }
            }
        }
        public SyncDigestEntryInfo Get(int resourceKindId, int EndPointId, IJetTransaction jetTransaction)
        {
            SyncDigestEntryInfo resultInfo = null;

            OleDbCommand oleDbCommand = jetTransaction.CreateOleCommand();

            string sqlQuery = string.Empty;

            sqlQuery = "SELECT {0}.Tick, {0}.ConflictPriority, {0}.Stamp, {1}.EndPoint FROM {1} INNER JOIN {0} ON {1}.ID={0}.FKEndPointId " +
            "WHERE ({0}.FKResourceKindId)=@ResourceKindId " +
            "AND ({0}.FKEndPointId)=@EndPointId;";

            oleDbCommand.CommandText = string.Format(sqlQuery, _syncDigestTable.TableName, _syncDigestTable.EndPointTable.TableName);

            oleDbCommand.Parameters.AddWithValue("@ResourceKindId", resourceKindId);
            oleDbCommand.Parameters.AddWithValue("@EndPointId", EndPointId);

            using (OleDbDataReader reader = oleDbCommand.ExecuteReader(CommandBehavior.Default))
            {
                if (reader.Read())
                {
                    string EndPoint;
                    int tick;
                    int conflictPriority;
                    DateTime stamp;

                    EndPoint = Convert.ToString(reader["EndPoint"]);
                    tick = Convert.ToInt32(reader["tick"]);
                    conflictPriority = Convert.ToInt32(reader["ConflictPriority"]);
                    stamp = Convert.ToDateTime(reader["Stamp"]);
                    resultInfo = new SyncDigestEntryInfo(EndPoint, tick, conflictPriority, stamp);
                }
            }
            return resultInfo;
        }
        public void Add(string resourceKind, SyncDigestEntryInfo info)
        {
            ISyncDigestTableAdapter syncDigestTableAdapter = StoreEnvironment.Resolve<ISyncDigestTableAdapter>(_context);
            IResourceKindTableAdapter resourceKindTableAdapter = StoreEnvironment.Resolve<IResourceKindTableAdapter>(_context);

            using (IJetTransaction jetTransaction = _jetConnectionProvider.GetTransaction(false))
            {
                ResourceKindInfo resourceKindInfo = resourceKindTableAdapter.GetOrCreate(resourceKind, jetTransaction);

                try
                {
                    syncDigestTableAdapter.Insert(resourceKindInfo.Id, new SyncDigestEntryInfo[] { info }, jetTransaction);
                }
                catch (OleDbException exception)
                {
                    if (exception.Errors.Count == 1 && exception.Errors[0].SQLState == "3022")
                        throw new StoreException(string.Format("An error occured while adding a new sync digest entry. A sync digest entry already exists for the resource kind '{0}' and endpoint '{1}.", resourceKind, info.Endpoint), exception);

                    throw;
                }

                jetTransaction.Commit();
            }
        }
        /*
        public void Update(string resourceKind, SyncDigestInfo info)
        {
            ISyncDigestTableAdapter syncDigestTableAdapter = StoreEnvironment.Resolve<ISyncDigestTableAdapter>(_context);
            IResourceKindTableAdapter resourceKindTableAdapter = StoreEnvironment.Resolve<IResourceKindTableAdapter>(_context);

            using (IJetTransaction jetTransaction = _jetConnectionProvider.GetTransaction(false))
            {
                ResourceKindInfo resourceKindInfo = resourceKindTableAdapter.GetOrCreate(resourceKind, jetTransaction);

                try
                {
                    syncDigestTableAdapter.Update(resourceKindInfo.Id, info.ToArray(), jetTransaction);
                }
                catch (StoreException exception)
                {
                    throw new StoreException(string.Format("An error occured while updating a sync digest entry. No sync digest entry exists for the resource kind '{0}'.", resourceKind), exception);
                }
                jetTransaction.Commit();
            }
        }
        */
        public bool Update(string resourceKind, SyncDigestEntryInfo info)
        {
            bool result = false;
            ISyncDigestTableAdapter syncDigestTableAdapter = StoreEnvironment.Resolve<ISyncDigestTableAdapter>(_context);
            IResourceKindTableAdapter resourceKindTableAdapter = StoreEnvironment.Resolve<IResourceKindTableAdapter>(_context);

            using (IJetTransaction jetTransaction = _jetConnectionProvider.GetTransaction(false))
            {
                ResourceKindInfo resourceKindInfo = resourceKindTableAdapter.GetOrCreate(resourceKind, jetTransaction);

                result = syncDigestTableAdapter.Update(resourceKindInfo.Id,  info , jetTransaction);

                jetTransaction.Commit();
            }
            return result;
        }
        /*
        public void Put(string resourceKind, SyncDigestInfo info)
        {
            if (null == resourceKind)
                throw new ArgumentNullException("resourceKind");
            if (resourceKind == String.Empty)
                throw new ArgumentException("Parameter value is empty.", "resourceKind");

            if (null == info)
                throw new ArgumentNullException("info");

            // TODO: Validate entry property values

            // We set the priority on 'update'.
            lock (lockObj)
            {
                //try
                //{
                //    _provider.Update(resourceKind, info);
                //}
                //catch (StoreException)
                //{
                //    _provider.Add(resourceKind, info);
                //}

        #warning WORKAROUND for bug in Update Method
                // WORKAROUND
                // Update method does not throw any exception if entry did not exist.
                try
                {
                    _provider.Add(resourceKind, info);
                }
                catch (StoreException)
                {
                    _provider.Update(resourceKind, info);
                }
            }
        }
         * */
        //public void PersistNewer(string resourceKind, SyncState syncState)
        //{
        //    if (null == resourceKind)
        //        throw new ArgumentNullException("resourceKind");
        //    if (resourceKind == String.Empty)
        //        throw new ArgumentException("Parameter value is empty.", "resourceKind");
        //    if (null == syncState)
        //        throw new ArgumentNullException("syncState");
        //    lock (lockObj)
        //    {
        //        SyncDigestEntryInfo entry = _provider.Get(resourceKind, syncState.EndPoint);
        //        if (entry != null)
        //        {
        //            if (entry.Tick < syncState.tick+1)
        //            {
        //                entry.Tick = syncState.tick+1;
        //                _provider.Update(resourceKind, entry);
        //            }
        //        }
        //        else
        //        {
        //            entry = new SyncDigestEntryInfo(syncState.EndPoint, syncState.tick+1, 0, DateTime.Now);
        //            _provider.Add(resourceKind, entry);
        //        }
        //    }
        //}
        public void PersistNewer(string resourceKind, ResSyncInfo resSyncInfo)
        {
            if (null == resourceKind)
                throw new ArgumentNullException("resourceKind");
            if (resourceKind == String.Empty)
                throw new ArgumentException("Parameter value is empty.", "resourceKind");
            if (null == resSyncInfo)
                throw new ArgumentNullException("resSyncInfo");

            lock (lockObj)
            {
                SyncDigestEntryInfo entry = _provider.Get(resourceKind, resSyncInfo.EndPoint);
                if (entry != null)
                {
                    if (entry.Tick < resSyncInfo.Tick+1)
                    {
                        entry.Tick = resSyncInfo.Tick+1;
                        _provider.Update(resourceKind, entry);
                    }
                }
                else
                {
                    entry = new SyncDigestEntryInfo(resSyncInfo.EndPoint, resSyncInfo.Tick + 1, 1, DateTime.Now);
                    _provider.Add(resourceKind, entry);
                }
            }
        }
        public bool Update(int resourceKindId, SyncDigestEntryInfo syncDigestEntryInfo, IJetTransaction jetTransaction)
        {
            IEndPointTableAdapter EndPointTableAdapter = StoreEnvironment.Resolve<IEndPointTableAdapter>(this.Context);
            OleDbCommand oleDbCommand = jetTransaction.CreateOleCommand();
            EndPointInfo tmpEndPointInfo;

            string sqlQuery = string.Empty;
            sqlQuery = "UPDATE [{0}] SET [tick]=@tick, [ConflictPriority]=@ConflictPriority, [Stamp]=@Stamp WHERE (FKResourceKindId=@ResourceKindId AND FKEndPointId=@EndPointId);";

            oleDbCommand.CommandText = string.Format(sqlQuery, _syncDigestTable.TableName);

            // TODO: Use prepared query
            tmpEndPointInfo = EndPointTableAdapter.GetOrCreate(syncDigestEntryInfo.EndPoint, jetTransaction);
            oleDbCommand.Parameters.AddWithValue("@tick", syncDigestEntryInfo.Tick);
            oleDbCommand.Parameters.AddWithValue("@ConflictPriority", syncDigestEntryInfo.ConflictPriority);
            oleDbCommand.Parameters.AddWithValue("@Stamp", syncDigestEntryInfo.Stamp.ToString());
            oleDbCommand.Parameters.AddWithValue("@ResourceKindId", resourceKindId);
            oleDbCommand.Parameters.AddWithValue("@EndPointId", tmpEndPointInfo.Id);

            int count = oleDbCommand.ExecuteNonQuery();
            return (count > 0);
        }
        public void Insert(int resourceKindId, SyncDigestEntryInfo[] syncDigestEntryInfo, IJetTransaction jetTransaction)
        {
            IEndPointTableAdapter EndPointTableAdapter = StoreEnvironment.Resolve<IEndPointTableAdapter>(this.Context);
            OleDbCommand oleDbCommand = jetTransaction.CreateOleCommand();
            EndPointInfo tmpEndPointInfo;

            string sqlQuery = string.Empty;
            sqlQuery = "INSERT INTO [{0}] ([tick], [ConflictPriority], [Stamp], [FKResourceKindId], [FKEndPointId]) VALUES (@tick, @ConflictPriority, @Stamp, @ResourceKindId, @EndPointId);";

            oleDbCommand.CommandText = string.Format(sqlQuery, _syncDigestTable.TableName);

            foreach (SyncDigestEntryInfo info in syncDigestEntryInfo)
            {
                // TODO: Use prepared query
                tmpEndPointInfo = EndPointTableAdapter.GetOrCreate(info.EndPoint, jetTransaction);
                //oleDbCommand.Parameters.Clear();
                oleDbCommand.Parameters.AddWithValue("@tick", info.Tick);
                oleDbCommand.Parameters.AddWithValue("@ConflictPriority", info.ConflictPriority);
                oleDbCommand.Parameters.AddWithValue("@Stamp", info.Stamp.ToString());
                oleDbCommand.Parameters.AddWithValue("@ResourceKindId", resourceKindId);
                oleDbCommand.Parameters.AddWithValue("@EndPointId", tmpEndPointInfo.Id);

                oleDbCommand.ExecuteNonQuery();
            }
        }