博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
csharp: LocalDataCache.sync
阅读量:5079 次
发布时间:2019-06-12

本文共 30311 字,大约阅读时间需要 101 分钟。

app.config:

http://yourserver/Service.asmx

  

using System;using System.Collections.Generic;using System.Text;using Microsoft.Synchronization.Data;using Microsoft.Synchronization.Data.SqlServerCe;using Microsoft.Synchronization;namespace GBADeviceClient.Sync{    public class ClientSyncAgent : SyncAgent    {        public ClientSyncAgent()        {            //Hook between SyncAgent and SqlCeClientSyncProvider            this.LocalProvider = new SqlCeClientSyncProvider(Settings.Default.LocalConnectionString, true);                        //Adds the JobList and PropertyDetails tables to the SyncAgent             //setting the SyncDirection to bidirectional             //drop and recreate the table if exists            this.Configuration.SyncTables.Add("JobList");            this.Configuration.SyncTables.Add("PropertyDetails");            this.Configuration.SyncTables["JobList"].SyncDirection = SyncDirection.Bidirectional;            this.Configuration.SyncTables["JobList"].CreationOption = TableCreationOption.DropExistingOrCreateNewTable;            this.Configuration.SyncTables["PropertyDetails"].SyncDirection = SyncDirection.Bidirectional;            this.Configuration.SyncTables["PropertyDetails"].CreationOption = TableCreationOption.DropExistingOrCreateNewTable;                        // The ServerSyncProviderProxy is a type used to abstract the particular transport            // It simply uses reflection to map known method names required by the SyncProvider            // In this case, we hand edited a Web Service proxy             // The web service proxy required editing as VS generates proxies for all types returned by a web servcie            // In this case, we have all the types for Sync Services, and duplicating types will cause errors            this.RemoteProvider =                 new ServerSyncProviderProxy(                    new Sync.ConfiguredSyncWebServiceProxy(Settings.Default.WebServiceURL));        }    }}

  

using System;using System.Linq;using System.Collections.Generic;using System.Windows.Forms;using System.Data.SqlServerCe;namespace GBADeviceClient{    ///     /// https://www.microsoft.com/zh-cn/download/details.aspx?id=15784  Microsoft Synchronization Services for ADO.NET - 简体中文    /// https://www.microsoft.com/zh-CN/download/details.aspx?id=6497  Microsoft SQL Server Compact 3.5 联机丛书和示例    /// System.Data.SqlServerCe    /// C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Devices     /// 如何:将本地数据库和远程数据库配置为双向同步     /// https://docs.microsoft.com/zh-cn/previous-versions/bb629326%28v%3dvs.110%29    /// https://www.codeproject.com/Articles/22122/Database-local-cache    /// https://docs.microsoft.com/zh-cn/previous-versions/aa983341%28v%3dvs.110%29 SQL Server Compact 4.0 和 Visual Studio    /// https://www.microsoft.com/en-us/download/details.aspx?id=21880 Microsoft SQL Server Compact 4.0 Books Online    ///     static class Program    {        ///         /// The main entry point for the application.        ///         [MTAThread]        static void Main()        {            //Validate the database exists            // If the local database doesn't exist, the app requires initilization            using (SqlCeConnection conn = new SqlCeConnection(Settings.Default.LocalConnectionString))            {                if (!System.IO.File.Exists(conn.Database))                {                    DialogResult result = MessageBox.Show(                        "The application requires a first time sync to continue.  Would you like to Sync Now?",                        "Fist Time Run",                        MessageBoxButtons.OKCancel,                        MessageBoxIcon.Exclamation,                        MessageBoxDefaultButton.Button1);                    if (result == DialogResult.OK)                    {                        try                        {                            using (SynchronizingProgress progressForm = new SynchronizingProgress())                            {                                // Pop a Progress form to get the cursor and provide feedback                                // on what's happening                                // The current UI is simply to make sure the wiat cursor shows                                progressForm.Show();                                // Make sure the form is displayed                                Application.DoEvents();                                Cursor.Current = Cursors.WaitCursor;                                Cursor.Show();                                Sync.ClientSyncAgent syncAgent = new Sync.ClientSyncAgent();                                syncAgent.Synchronize();                            }                        }                        catch (Exception ex)                        {                            // Oooops, something happened                            MessageBox.Show(                                "Unable to synchronize..." + Environment.NewLine + ex.ToString(),                                "Error during initial sync",                                 MessageBoxButtons.OK,                                 MessageBoxIcon.Exclamation,                                 MessageBoxDefaultButton.Button1);                        }                        finally                        {                            //Always, always, be sure to reset the cursor                            Cursor.Current = Cursors.Default;                        }                    }                    else                        return;                } // If database exists            } // Using conn                         // Good to go            Application.Run(new GBAppraiseUI());        }    }}

  

https://www.codeproject.com/Articles/22122/Database-local-cache

 

using System;using System.Collections.Generic;using System.Data;using System.Data.SqlClient;using System.Globalization;using System.IO;using System.Reflection;using System.Text.RegularExpressions;using System.Data.Common;namespace Konamiman.Data{    ///     /// Represents a local filesystem based cache for binary objects stored in a database https://www.codeproject.com/Articles/22122/Database-local-cache    ///     /// 
///
/// This class allows you to store binary objects in a database table, but using the a local filesystem cache /// to increase the data retrieval speed when requesting the same data repeatedly. ///
///
/// To use the class, you need a table with three columns: a string column for the object name /// (objects are uniquely identified by their names), a binary column /// for the object value, and a timestamp column (any column type is ok as long as the column value automatically changes /// when the value column changes). You need also a directory in the local filesystem. You specify these values /// in the class constructor, or via class properties. ///
///
/// When you first request an object, it is retrieved from the database and stored in the local cache. /// The next time you request the same object, the timestamps of the cached object and the database object /// are compared. If they match, the cached file is returned directly. Otherwise, the cached file is updated /// with the current object value from the database. ///
///
class DatabaseFileCache { #region Fields and properties //SQL commands used for database access SqlCommand selectValueCommand; SqlCommand selectTimestampCommand; SqlCommand fileExistsCommand; SqlCommand insertCommand; SqlCommand getNamesCommand; SqlCommand deleteCommand; SqlCommand renameCommand; //The local cache directory DirectoryInfo cacheDirectory; /// /// Gets or sets the maximum execution time for SQL commands, in seconds. /// ///
/// Default value is 30 seconds. A larger value may be needed when handling very big objects. ///
public int CommandTimeout { get { return selectValueCommand.CommandTimeout; } set { selectValueCommand.CommandTimeout = value; selectTimestampCommand.CommandTimeout = value; fileExistsCommand.CommandTimeout = value; insertCommand.CommandTimeout = value; getNamesCommand.CommandTimeout = value; deleteCommand.CommandTimeout = value; renameCommand.CommandTimeout = value; } } private SqlConnection _Connection; /// /// Gets or sets the connection object for database access. /// public SqlConnection Connection { get { return _Connection; } set { _Connection=value; CreateCommands(); } } private string _TableName; /// /// Gets or sets the name of the table that stores the binary objects in the database. /// public string TableName { get { return _TableName; } set { _TableName=value; UpdateCommandTexts(); } } private string _CachePath; /// /// Gets or sets the local cache path. /// ///
///
If a relative path is specified, it will be combined with the value of the global variable
DataDirectory, /// if it has a value at all. If not, the path will be combined with the application executable path. You can set the DataDirectory /// variable with this code:
AppDomain.CurrentDomain.SetData("DataDirectory", ruta)
///
When retrieving the value, the full path is returned, with DataDirectory or the application path appropriately expanded.
///
public string CachePath { get { return _CachePath; } set { string dataDirectory=(string)AppDomain.CurrentDomain.GetData("DataDirectory"); if(dataDirectory==null) dataDirectory=Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); _CachePath=Path.Combine(dataDirectory, value); cacheDirectory=new DirectoryInfo(_CachePath); } } private string _NameColumn; /// /// Gets or sets the name of the column for the object name in the database table that stores the binary objects /// ///
/// Binary objects are uniquely identified by their names. This column should be defined with a "unique" /// constraint in the database, but this is not mandatory. ///
public string NameColumn { get { return _NameColumn; } set { _NameColumn=value; UpdateCommandTexts(); } } private string _ValueColumn; /// /// Gets or sets the name of the column for the object contents in the database table that stores the binary objects /// ///
/// This column may be of any data type that ADO.NET can convert to and from byte arrays. ///
public string ValueColumn { get { return _ValueColumn; } set { _ValueColumn=value; UpdateCommandTexts(); } } private string _TimestampColumn; /// /// Gets or sets the name of the column for the timestamp in the database table that stores the binary objects /// ///
/// This column may be of any data type that ADO.NET can convert to and from byte arrays. /// Also, the column value must automatically change when the value column changes. ///
public string TimestampColumn { get { return _TimestampColumn; } set { _TimestampColumn=value; UpdateCommandTexts(); } } #endregion #region Constructors // Parameterless constructor is declared as private to avoid creating instances with no associated connection object private DatabaseFileCache() { } /// /// Creates a new instance of the class. /// /// Connection object for database access. /// Name of the table that stores the binary objects in the database. /// Local cache path (absolute or relative, see property CachePath). /// Name of the column for the object name in the database table that stores the binary objects. /// Name of the column for the object contents in the database table that stores the binary objects. /// Name of the column for the timestamp in the database table that stores the binary objects. public DatabaseFileCache(SqlConnection connection, string tableName, string cachePath, string nameColumn, string valueColumn, string timestampColumn) { _TableName=tableName; CachePath=cachePath; _NameColumn=nameColumn; _ValueColumn=valueColumn; _TimestampColumn=timestampColumn; Connection=connection; } /// /// Creates a new instance of the class, assuming the default names Name, Value and timestamp for the names /// of the columns in the database table that stores the binary objects. /// /// Connection object for database access. /// Name of the table that stores the binary objects in the database. /// Local cache path (absolute or relative, see property CachePath). public DatabaseFileCache(SqlConnection connection, string tableName, string cachePath) : this(connection, tableName, cachePath, "Name", "Value", "timestamp") { } /// /// Creates a new instance of the class, assuming the default names Name, Value and timestamp for the names. /// Also, assumes that the table name is Objects, and sets the local cache path to the relative name DatabaseCache /// (see property CachePath). /// /// Connection object for database access. public DatabaseFileCache(SqlConnection connection) : this(connection, "Objects", "DatabaseCache") { } #endregion #region Public methods /// /// Obtains a binary object from the local cache, retrieving it first from the database if necessary. /// ///
///
/// A database connection is first established to check that an object with the specified name actually exists in the database. /// If not,
null is returned. ///
///
/// Then the local cache is examinated to see if the object has been already cached. If not, the whole object is /// retrieved from the database, the cached file is created, and the file path is returned. ///
///
/// If the object was already cached, the timestamp of both the database object and the cached file are compared. /// If they are equal, the cached file path is returned directly. Otherwise, the cached file is recreated /// from the updated object data in the database. ///
///
/// Name of the object to retrieve. ///
Full path of the cached file, or
null if there is not an object with such name in the database.
public string GetObject(string objectName) { Connection.Open(); try { //* Obtain object timestamp from the database selectTimestampCommand.Parameters["@name"].Value=objectName; byte[] timestampBytes=(byte[])selectTimestampCommand.ExecuteScalar(); if(timestampBytes==null) return null; //No object with such name found in the database string timestamp=""; foreach(byte b in timestampBytes) timestamp+=b.ToString("X").PadLeft(2, '0'); //* Checks that the object is cached and that the cached file is up to date string escapedFileName=EscapeFilename(objectName); FileInfo[] fileInfos=cacheDirectory.GetFiles(EscapeFilename(objectName)+".*"); if(fileInfos.Length>0) { string cachedTimestamp=Path.GetExtension(fileInfos[0].Name); if(cachedTimestamp==timestamp) return fileInfos[0].FullName; //Up to date cached version exists: return it else fileInfos[0].Delete(); //Outdated cached version exists: delete it } //* Object was not cached or cached file was outdated: retrieve it from database and cache it string fullLocalFileName=Path.Combine(CachePath, escapedFileName)+"."+timestamp; selectValueCommand.Parameters["@name"].Value=objectName; File.WriteAllBytes(fullLocalFileName, (byte[])selectValueCommand.ExecuteScalar()); return fullLocalFileName; } finally { Connection.Close(); } } /// /// Obtains the cached version of a database object, if it exists. /// /// Name of the object whose cached version is to be retrieved. ///
Full path of the cached file, or
null if there the specified object is not cached.
///
/// This method does not access the database at all, it only checks the local cache. /// It should be used only when the database becomes unreachable, and only if it is acceptable /// to use data that may be outdated. ///
public string GetCachedFile(string objectName) { FileInfo[] fileInfos=cacheDirectory.GetFiles(EscapeFilename(objectName)+".*"); if(fileInfos.Length>0) return fileInfos[0].FullName; else return null; } /// /// Creates or updates a binary object in the database from a byte array. /// /// Contents of the binary object. /// Object name. ///
/// If there is already an object with the specified name in the database, its contents are updated. /// Otherwise, a new object record is created. ///
public void SaveObject(byte[] value, string objectName) { insertCommand.Parameters["@name"].Value=objectName; insertCommand.Parameters["@value"].Value=value; Connection.Open(); try { insertCommand.ExecuteNonQuery(); } finally { Connection.Close(); } } /// /// Creates or updates a binary object in the database from the contents of a file. /// /// Full path of the file containing the object data. /// Object name. ///
/// If there is already an object with the specified name in the database, its contents are updated. /// Otherwise, a new object record is created. ///
public void SaveObject(string filePath, string objectName) { SaveObject(File.ReadAllBytes(filePath), objectName); } /// /// Creates or updates a binary object in the database from the contents of a file, /// using the file name (without path) as the object name. /// /// Full path of the file containing the object data. ///
/// If there is already an object with the specified name in the database, its contents are updated. /// Otherwise, a new object record is created. ///
public void SaveObject(string filePath) { SaveObject(filePath, Path.GetFileName(filePath)); } /// /// Deletes an object from the database and from the local cache. /// /// Object name. ///
/// If the object does not exist in the database, nothing happens and no error is returned. ///
public void DeleteObject(string objectName) { //* Delete object from database deleteCommand.Parameters["@name"].Value=objectName; Connection.Open(); try { deleteCommand.ExecuteNonQuery(); } finally { Connection.Close(); } //* Delete object from local cache FileInfo[] files=cacheDirectory.GetFiles(EscapeFilename(objectName)+".*"); foreach(FileInfo file in files) file.Delete(); } /// /// Changes the name of an object in the database, and in the local cache. /// /// Old object name. /// New object name. ///
/// If the object does not exist in the database, nothing happens and no error is returned. ///
public void RenameObject(string oldName, string newName) { //* Rename object in database renameCommand.Parameters["@oldName"].Value=oldName; renameCommand.Parameters["@newName"].Value=newName; Connection.Open(); try { renameCommand.ExecuteNonQuery(); } finally { Connection.Close(); } //* Rename object in local cache string escapedOldName=EscapeFilename(oldName); string escapedNewName=EscapeFilename(newName); FileInfo[] files=cacheDirectory.GetFiles(escapedOldName+".*"); foreach(FileInfo file in files) { string timestamp=Path.GetExtension(file.Name); file.MoveTo(Path.Combine(CachePath, escapedNewName+timestamp)); } } /// /// Deletes all cached files that have no matching object in the database. /// ///
/// Cached files with no matching object in the database could appear if another user /// (or another application) deletes an object that was already cached. ///
public void PurgeCache() { List
databaseObjectNames=new List
(GetObjectNames()); FileInfo[] files=cacheDirectory.GetFiles(); foreach(FileInfo file in files) { if(!databaseObjectNames.Contains(UnescapeFilename(Path.GetFileNameWithoutExtension(file.Name)))) file.Delete(); } } ///
/// Checks whether an object exists in the database or not. /// ///
Object name. ///
True if there is an object with the specified name in the database,
False otherwise.
///
/// The local cache is not accessed, only the database is checked. ///
public bool ObjectExists(string objectName) { fileExistsCommand.Parameters["@name"].Value=objectName; Connection.Open(); try { int exists=(int)fileExistsCommand.ExecuteScalar(); return exists==1; } finally { Connection.Close(); } } ///
/// Obtains the names of all the objects stored in the database. /// ///
Names of all the objects stored in the database.
///
/// The local cache is not accessed, only the database is checked. ///
public string[] GetObjectNames() { List
names=new List
(); Connection.Open(); try { SqlDataReader reader=getNamesCommand.ExecuteReader(); while(reader.Read()) { names.Add(reader.GetString(0)); } reader.Close(); return names.ToArray(); } finally { Connection.Close(); } } #endregion #region Private methods ///
/// Escapes an object name so that it is a valid filename. /// ///
Original object name. ///
Escaped name.
///
/// All characters that are not valid for a filename, plus "%" and ".", are converted into "%uuuu", where uuuu is the hexadecimal /// unicode representation of the character. ///
private string EscapeFilename(string fileName) { char[] invalidChars=Path.GetInvalidFileNameChars(); // Replace "%", then replace all other characters, then replace "." fileName=fileName.Replace("%", "%0025"); foreach(char invalidChar in invalidChars) { fileName=fileName.Replace(invalidChar.ToString(), string.Format("%{0,4:X}", Convert.ToInt16(invalidChar)).Replace(' ', '0')); } return fileName.Replace(".", "%002E"); } ///
/// Unescapes an escaped file name so that the original object name is obtained. /// ///
Escaped object name (see the EscapeFilename method). ///
Unescaped (original) object name.
public string UnescapeFilename(string escapedName) { //We need to temporarily replace %0025 with %! to prevent a name //originally containing escaped sequences to be unescaped incorrectly //(for example: ".%002E" once escaped is "%002E%0025002E". //If we don't do this temporary replace, it would be unescaped to "..") string unescapedName=escapedName.Replace("%0025", "%!"); Regex regex=new Regex("%(?
[0-9A-Fa-f]{4})"); Match m=regex.Match(escapedName); while(m.Success) { foreach(Capture cap in m.Groups["esc"].Captures) unescapedName=unescapedName.Replace("%"+cap.Value, Convert.ToChar(int.Parse(cap.Value, NumberStyles.HexNumber)).ToString()); m=m.NextMatch(); } return unescapedName.Replace("%!", "%"); } ///
/// Creates the commands for database access. /// ///
/// This method is executed when the Connection property changes. ///
private void CreateCommands() { selectValueCommand=Connection.CreateCommand(); selectValueCommand.Parameters.Add("@name", SqlDbType.NVarChar); selectTimestampCommand=Connection.CreateCommand(); selectTimestampCommand.Parameters.Add("@name", SqlDbType.NVarChar); fileExistsCommand=Connection.CreateCommand(); fileExistsCommand.Parameters.Add("@name", SqlDbType.NVarChar); insertCommand=Connection.CreateCommand(); insertCommand.Parameters.Add("@name", SqlDbType.NVarChar); insertCommand.Parameters.Add("@value", SqlDbType.VarBinary); getNamesCommand=Connection.CreateCommand(); deleteCommand=Connection.CreateCommand(); deleteCommand.Parameters.Add("@name", SqlDbType.NVarChar); renameCommand=Connection.CreateCommand(); renameCommand.Parameters.Add("@oldName", SqlDbType.NVarChar); renameCommand.Parameters.Add("@newName", SqlDbType.NVarChar); UpdateCommandTexts(); } ///
/// Updates the text of the commands used for database access. /// ///
/// This method is executed when any of these properties change: TableName, NameColumn, ValueColumn, TimestampColumn. ///
private void UpdateCommandTexts() { selectValueCommand.CommandText=string.Format( "select {0} from {1} where {2}=@name", ValueColumn, TableName, NameColumn); selectTimestampCommand.CommandText=string.Format( "select {0} from {1} where {2}=@name", TimestampColumn, TableName, NameColumn); fileExistsCommand.CommandText=string.Format( "if exists(select {0} from {1} where {0}=@name) select 1; else select 0;", NameColumn, TableName); insertCommand.CommandText=string.Format( "if exists (select {0} from {1} where {0}=@name) update {1} set {2}=@value where {0}=@name; else insert into {1} ({0}, {2}) values (@name, @value);", NameColumn, TableName, ValueColumn); getNamesCommand.CommandText=string.Format("select {0} from {1}", NameColumn, TableName); deleteCommand.CommandText=string.Format( "delete from {0} where {1}=@name", TableName, NameColumn); renameCommand.CommandText=string.Format( "update {0} set {1}=@newName where {1}=@oldName", TableName, NameColumn); } #endregion }}

  

转载于:https://www.cnblogs.com/geovindu/p/10495991.html

你可能感兴趣的文章
重启rabbitmq服务
查看>>
正则表达式(进阶篇)
查看>>
无人值守安装linux系统
查看>>
【传道】中国首部淘宝卖家演讲公开课:农业本该如此
查看>>
jQuery应用 代码片段
查看>>
MVC+Servlet+mysql+jsp读取数据库信息
查看>>
黑马程序员——2 注释
查看>>
用OGRE1.74搭建游戏框架(三)--加入人物控制和场景
查看>>
转化课-计算机基础及上网过程
查看>>
android dialog使用自定义布局 设置窗体大小位置
查看>>
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Win 10 文件浏览器无法打开
查看>>
HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)
查看>>
-bash: xx: command not found 在有yum源情况下处理
查看>>
[leetcode]Minimum Path Sum
查看>>
内存管理 浅析 内存管理/内存优化技巧
查看>>
hiho1079 线段树区间改动离散化
查看>>