csharp: LocalDataCache.sync
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="GBADesktopClient.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="GBADesktopClient.Properties.Settings.ServerGBAppraiseDemoConnectionString"
connectionString="Data Source=.;Initial Catalog=GBAppraiseDemo;Persist Security Info=True;User ID=gbauser;Password=gbauser"
providerName="System.Data.SqlClient" />
<add name="GBADesktopClient.Properties.Settings.ClientGBAppraiseDemoConnectionString"
connectionString="Data Source=|DataDirectory|\GBAppraiseDemo.sdf;Max Database Size=2047"
providerName="Microsoft.SqlServerCe.Client.3.5" />
</connectionStrings>
<applicationSettings>
<GBADesktopClient.Properties.Settings>
<setting name="SyncWebServiceURL" serializeAs="String">
<value>http://yourserver/Service.asmx</value>
</setting>
</GBADesktopClient.Properties.Settings>
</applicationSettings>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IGBACacheSyncContract" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8080/GBACacheSyncService/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IGBACacheSyncContract"
contract="GBAConfiguredSyncWcfService.IGBACacheSyncContract"
name="WSHttpBinding_IGBACacheSyncContract">
</endpoint>
</client>
</system.serviceModel>
</configuration>
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
{ /// <summary>
/// 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
/// </summary>
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[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
{
/// <summary>
/// Represents a local filesystem based cache for binary objects stored in a database https://www.codeproject.com/Articles/22122/Database-local-cache
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
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; /// <summary>
/// Gets or sets the maximum execution time for SQL commands, in seconds.
/// </summary>
/// <remarks>
/// Default value is 30 seconds. A larger value may be needed when handling very big objects.
/// </remarks>
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;
/// <summary>
/// Gets or sets the connection object for database access.
/// </summary>
public SqlConnection Connection
{
get
{
return _Connection;
}
set
{
_Connection=value;
CreateCommands();
}
} private string _TableName;
/// <summary>
/// Gets or sets the name of the table that stores the binary objects in the database.
/// </summary>
public string TableName
{
get
{
return _TableName;
}
set
{
_TableName=value;
UpdateCommandTexts();
}
} private string _CachePath;
/// <summary>
/// Gets or sets the local cache path.
/// </summary>
/// <remarks>
/// <para>If a relative path is specified, it will be combined with the value of the global variable <b>DataDirectory</b>,
/// 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: <code>AppDomain.CurrentDomain.SetData("DataDirectory", ruta)</code></para>
/// <para>When retrieving the value, the full path is returned, with DataDirectory or the application path appropriately expanded.</para>
/// </remarks>
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;
/// <summary>
/// Gets or sets the name of the column for the object name in the database table that stores the binary objects
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public string NameColumn
{
get
{
return _NameColumn;
}
set
{
_NameColumn=value;
UpdateCommandTexts();
}
} private string _ValueColumn;
/// <summary>
/// Gets or sets the name of the column for the object contents in the database table that stores the binary objects
/// </summary>
/// <remarks>
/// This column may be of any data type that ADO.NET can convert to and from byte arrays.
/// </remarks>
public string ValueColumn
{
get
{
return _ValueColumn;
}
set
{
_ValueColumn=value;
UpdateCommandTexts();
}
} private string _TimestampColumn;
/// <summary>
/// Gets or sets the name of the column for the timestamp in the database table that stores the binary objects
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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() { } /// <summary>
/// Creates a new instance of the class.
/// </summary>
/// <param name="connection">Connection object for database access.</param>
/// <param name="tableName">Name of the table that stores the binary objects in the database.</param>
/// <param name="cachePath">Local cache path (absolute or relative, see property CachePath).</param>
/// <param name="nameColumn">Name of the column for the object name in the database table that stores the binary objects.</param>
/// <param name="valueColumn">Name of the column for the object contents in the database table that stores the binary objects.</param>
/// <param name="timestampColumn">Name of the column for the timestamp in the database table that stores the binary objects.</param>
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;
} /// <summary>
/// Creates a new instance of the class, assuming the default names <b>Name</b>, <b>Value</b> and <b>timestamp</b> for the names
/// of the columns in the database table that stores the binary objects.
/// </summary>
/// <param name="connection">Connection object for database access.</param>
/// <param name="tableName">Name of the table that stores the binary objects in the database.</param>
/// <param name="cachePath">Local cache path (absolute or relative, see property CachePath).</param>
public DatabaseFileCache(SqlConnection connection, string tableName, string cachePath)
: this(connection, tableName, cachePath, "Name", "Value", "timestamp") { } /// <summary>
/// Creates a new instance of the class, assuming the default names <b>Name</b>, <b>Value</b> and <b>timestamp</b> for the names.
/// Also, assumes that the table name is <b>Objects</b>, and sets the local cache path to the relative name <b>DatabaseCache</b>
/// (see property CachePath).
/// </summary>
/// <param name="connection">Connection object for database access.</param>
public DatabaseFileCache(SqlConnection connection)
: this(connection, "Objects", "DatabaseCache") { } #endregion #region Public methods /// <summary>
/// Obtains a binary object from the local cache, retrieving it first from the database if necessary.
/// </summary>
/// <remarks>
/// <para>
/// A database connection is first established to check that an object with the specified name actually exists in the database.
/// If not, <b>null</b> is returned.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
/// <param name="objectName">Name of the object to retrieve.</param>
/// <returns>Full path of the cached file, or <i>null</i> if there is not an object with such name in the database.</returns>
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();
}
} /// <summary>
/// Obtains the cached version of a database object, if it exists.
/// </summary>
/// <param name="objectName">Name of the object whose cached version is to be retrieved.</param>
/// <returns>Full path of the cached file, or <i>null</i> if there the specified object is not cached.</returns>
/// <remarks>
/// 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.
/// </remarks>
public string GetCachedFile(string objectName)
{
FileInfo[] fileInfos=cacheDirectory.GetFiles(EscapeFilename(objectName)+".*");
if(fileInfos.Length>0)
return fileInfos[0].FullName;
else
return null;
} /// <summary>
/// Creates or updates a binary object in the database from a byte array.
/// </summary>
/// <param name="value">Contents of the binary object.</param>
/// <param name="objectName">Object name.</param>
/// <remarks>
/// If there is already an object with the specified name in the database, its contents are updated.
/// Otherwise, a new object record is created.
/// </remarks>
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();
}
} /// <summary>
/// Creates or updates a binary object in the database from the contents of a file.
/// </summary>
/// <param name="filePath">Full path of the file containing the object data.</param>
/// <param name="objectName">Object name.</param>
/// <remarks>
/// If there is already an object with the specified name in the database, its contents are updated.
/// Otherwise, a new object record is created.
/// </remarks>
public void SaveObject(string filePath, string objectName)
{
SaveObject(File.ReadAllBytes(filePath), objectName);
} /// <summary>
/// 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.
/// </summary>
/// <param name="filePath">Full path of the file containing the object data.</param>
/// <remarks>
/// If there is already an object with the specified name in the database, its contents are updated.
/// Otherwise, a new object record is created.
/// </remarks>
public void SaveObject(string filePath)
{
SaveObject(filePath, Path.GetFileName(filePath));
} /// <summary>
/// Deletes an object from the database and from the local cache.
/// </summary>
/// <param name="objectName">Object name.</param>
/// <remarks>
/// If the object does not exist in the database, nothing happens and no error is returned.
/// </remarks>
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();
} /// <summary>
/// Changes the name of an object in the database, and in the local cache.
/// </summary>
/// <param name="oldName">Old object name.</param>
/// <param name="newName">New object name.</param>
/// <remarks>
/// If the object does not exist in the database, nothing happens and no error is returned.
/// </remarks>
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));
}
} /// <summary>
/// Deletes all cached files that have no matching object in the database.
/// </summary>
/// <remarks>
/// Cached files with no matching object in the database could appear if another user
/// (or another application) deletes an object that was already cached.
/// </remarks>
public void PurgeCache()
{
List<string> databaseObjectNames=new List<string>(GetObjectNames());
FileInfo[] files=cacheDirectory.GetFiles();
foreach(FileInfo file in files)
{
if(!databaseObjectNames.Contains(UnescapeFilename(Path.GetFileNameWithoutExtension(file.Name))))
file.Delete();
}
} /// <summary>
/// Checks whether an object exists in the database or not.
/// </summary>
/// <param name="objectName">Object name.</param>
/// <returns><b>True</b> if there is an object with the specified name in the database, <b>False</b> otherwise.</returns>
/// <remarks>
/// The local cache is not accessed, only the database is checked.
/// </remarks>
public bool ObjectExists(string objectName)
{
fileExistsCommand.Parameters["@name"].Value=objectName;
Connection.Open();
try
{
int exists=(int)fileExistsCommand.ExecuteScalar();
return exists==1;
}
finally
{
Connection.Close();
}
} /// <summary>
/// Obtains the names of all the objects stored in the database.
/// </summary>
/// <returns>Names of all the objects stored in the database.</returns>
/// <remarks>
/// The local cache is not accessed, only the database is checked.
/// </remarks>
public string[] GetObjectNames()
{
List<string> names=new List<string>();
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 /// <summary>
/// Escapes an object name so that it is a valid filename.
/// </summary>
/// <param name="fileName">Original object name.</param>
/// <returns>Escaped name.</returns>
/// <remarks>
/// 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.
/// </remarks>
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");
} /// <summary>
/// Unescapes an escaped file name so that the original object name is obtained.
/// </summary>
/// <param name="escapedName">Escaped object name (see the EscapeFilename method).</param>
/// <returns>Unescaped (original) object name.</returns>
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("%(?<esc>[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("%!", "%");
} /// <summary>
/// Creates the commands for database access.
/// </summary>
/// <remarks>
/// This method is executed when the Connection property changes.
/// </remarks>
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();
} /// <summary>
/// Updates the text of the commands used for database access.
/// </summary>
/// <remarks>
/// This method is executed when any of these properties change: TableName, NameColumn, ValueColumn, TimestampColumn.
/// </remarks>
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
}
}
csharp: LocalDataCache.sync的更多相关文章
- CSharp for Jupyter Notebook
之前说有机会就说下Linux下如何搭建C#版的交互编程,今天写篇文章还债^_^ Win下比较简单,可以自己看官方文档,下面逆天带大家搭建下Linux下的环境(官方方法有问题) 在线预览:https:/ ...
- c#操作MangoDB 之MangoDB CSharp Driver驱动详解
序言 MangoDB CSharp Driver是c#操作mongodb的官方驱动. 官方Api文档:http://api.mongodb.org/csharp/2.2/html/R_Project_ ...
- Gradle project sync failed
在Android Studio中运行APP时出现了以下错误: gradle project sync failed. please fix your project and try again 解决的 ...
- c#进阶之神奇的CSharp
CSharp 简写为c#,是一门非常年轻而又有活力的语言. CSharp的诞生 在2000年6月微软发布了c#这门新的语言.作为微软公司.NET 平台的主角,c#吸收了在他之前诞生的语言(c ...
- svn sync主从同步学习
svn备份的方式有三种: 1svnadmin dump 2)svnadmin hotcopy 3)svnsync. 优缺点分析============== 第一种svnadmin dump是官方推荐 ...
- ASP.NET sync over async(异步中同步,什么鬼?)
async/await 是我们在 ASP.NET 应用程序中,写异步代码最常用的两个关键字,使用它俩,我们不需要考虑太多背后的东西,比如异步的原理等等,如果你的 ASP.NET 应用程序是异步到底的, ...
- publishing failed with multiple errors resource is out of sync with the file system--转
原文地址:http://blog.csdn.net/feng1603/article/details/7398266 今天用eclipse部署项目遇到"publishing failed w ...
- WindowsCE project missing Microsoft.CompactFramework.CSharp.targets in Visual Studio 2008
00x0 前言 之前在Windows 7系统中开发的WindowsCE项目,最近换成Windows 10系统,需要将项目进行修改,打开项目后提示如下错误: 无法读取项目文件"App.cspr ...
- csharp: Oracle Stored Procedure DAL using ODP.NET
paging : http://www.codeproject.com/Articles/44858/Custom-Paging-GridView-in-ASP-NET-Oracle https:// ...
随机推荐
- Linux入门总结——虚拟机安装配置以及vim简单操作
安装配置ubuntu 安装准备 vittualbox-5.2.22版本(win10) ubuntu-12.04 安装VirtualBox 1.双击VirtualBox-5.2.2-119230-Win ...
- FCC(ES6写法)Pairwise
举个例子:有一个能力数组[7,9,11,13,15],按照最佳组合值为20来计算,只有7+13和9+11两种组合.而7在数组的索引为0,13在数组的索引为3,9在数组的索引为1,11在数组的索引为2. ...
- C语言面试题分类->链表
链表的创建,清空,插入,删除 typedef int (* __compfunc)(const void *, const void *); //Traverse list. Fast macro t ...
- [Swift]LeetCode12. 整数转罗马数字 | Integer to Roman
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 ...
- [Swift]LeetCode266.回文全排列 $ Palindrome Permutation
Given a string, determine if a permutation of the string could form a palindrome. For example," ...
- [Swift]LeetCode434. 字符串中的单词数 | Number of Segments in a String
Count the number of segments in a string, where a segment is defined to be a contiguous sequence of ...
- JS异步解析
同步和异步 举个
- SpringBoot 集成Mybatis 连接Mysql数据库
记录SpringBoot 集成Mybatis 连接数据库 防止后面忘记 1.添加Mybatis和Mysql依赖 <dependency> <groupId>org.mybati ...
- Java IO流读取文件
使用指定编码读取文件 public static String toString(File file, String charset){ StringBuilder result = new Stri ...
- ECMAScript 6 学习(一)generator函数
1.ES2017标准引入async函数,那么async函数到底是个什么函数呢? async 是一个generator函数的语法糖. 2.那么generator函数到底是什么函数ne? generato ...