1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Tango.Scripting;
namespace TestApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private IScriptingEngine _engine;
private ScriptSession _session;
public MainWindow()
{
InitializeComponent();
_engine = new ScriptingEngine();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
Script s = new Script();
s.Code =
@"
using System;
using System.Windows.Forms;
MessageBox.Show(""Hi Roy"");
";
try
{
_session = await _engine.Run(s);
_session.StateChanged += Session_StateChanged;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void Session_StateChanged(object sender, ScriptSessionStateChangedEventArgs e)
{
if (e.State == ScriptSessionState.Completed)
{
MessageBox.Show(e.ReturnValue.ToString());
}
else if (e.State == ScriptSessionState.Aborted)
{
MessageBox.Show("Aborted");
}
else if (e.State == ScriptSessionState.Failed)
{
MessageBox.Show(e.Exception.ToString());
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
_session.Abort();
}
}
}
ransparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */using Tango.Synchronization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Tango.Synchronization.Local
{
/// <summary>
/// Represents an SQLite database adapter used for synchronization by <see cref="LocalDBComparer"/>.
/// </summary>
/// <seealso cref="Tango.Synchronization.ISqlDataBase" />
public class SQLiteDataBase : ILocalDataBase
{
private SQLiteConnection _connection;
/// <summary>
/// Gets the database source URL/File.
/// </summary>
public String Source { get; private set; }
/// <summary>
/// Gets the database tables collection.
/// </summary>
public List<DataTable> Tables { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="SQLiteDataBase"/> class.
/// </summary>
/// <param name="filePath">The file path.</param>
public SQLiteDataBase(String filePath)
{
Source = filePath;
_connection = new SQLiteConnection(String.Format("Data Source={0};Version=3;New={1};Compress=FALSE;",
filePath,
(File.Exists(filePath) ? "False" : "True")
));
_connection.Open();
}
/// <summary>
/// Loads the tables (Must be done before any synchronization).
/// </summary>
public void LoadTables()
{
Tables = new List<DataTable>();
var command = _connection.CreateCommand();
command.CommandText = "SELECT name FROM sqlite_master WHERE type = 'table'";
var reader = command.ExecuteReader();
while (reader.Read())
{
String name = reader.GetString(0);
if (name != Constants.SEQUENCE_TABLE_NAME)
{
Debug.WriteLine(name);
Tables.Add(LoadTable(name));
}
}
}
/// <summary>
/// Loads the table.
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
private DataTable LoadTable(String name)
{
var tableCommand = _connection.CreateCommand();
tableCommand.CommandText = "SELECT * FROM " + name;
DataTable table = new DataTable(name);
table.Load(tableCommand.ExecuteReader());
var infoCommand = _connection.CreateCommand();
infoCommand.CommandText = String.Format("PRAGMA table_info({0});", name);
DataTable infoTable = new DataTable(name);
infoTable.Load(infoCommand.ExecuteReader());
table.ExtendedProperties.Add(Constants.TABLE_INFO, infoTable);
for (int i = 0; i < table.Columns.Count; i++)
{
DataColumn column = table.Columns[i];
column.ExtendedProperties.Add(Constants.COLUMN_TYPE, infoTable.Rows[i][Constants.COLUMN_TYPE]);
column.ExtendedProperties.Add(Constants.IS_NOT_NULL, infoTable.Rows[i][Constants.IS_NOT_NULL]);
column.ExtendedProperties.Add(Constants.DEFAULT_VALUE, infoTable.Rows[i][Constants.DEFAULT_VALUE]);
}
return table;
}
/// <summary>
/// Clears the data base.
/// </summary>
public void ClearDataBase()
{
foreach (var table in Tables)
{
var dropCommand = _connection.CreateCommand();
dropCommand.CommandText = String.Format("DELETE FROM {0};", table.TableName);
dropCommand.ExecuteNonQuery();
}
}
/// <summary>
/// Clones a table from another database into this database.
/// </summary>
/// <param name="otherDB">The other database.</param>
/// <param name="otherTable">The other table.</param>
/// <returns></returns>
public DataTable CloneTableFrom(ILocalDataBase otherDB, DataTable otherTable)
{
String cmd = String.Format("CREATE TABLE {0} (", otherTable.TableName);
foreach (DataColumn column in otherTable.Columns)
{
cmd += String.Format("{0} {1} {2} {3} {4} {5}",
column.ColumnName,
column.GetSQLType(),
otherTable.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
column.Unique ? "UNIQUE" : null,
column.IsNotNull() ? "NOT NULL" : null,
column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null)
+ ", " + Environment.NewLine;
}
cmd += ");";
cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
var createCommand = _connection.CreateCommand();
createCommand.CommandText = cmd;
createCommand.ExecuteNonQuery();
var attacheCommand = _connection.CreateCommand();
attacheCommand.CommandText = String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source);
attacheCommand.ExecuteNonQuery();
var copyCommand = _connection.CreateCommand();
copyCommand.CommandText = String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other");
copyCommand.ExecuteNonQuery();
var detacheCommand = _connection.CreateCommand();
detacheCommand.CommandText = "DETACH other;";
detacheCommand.ExecuteNonQuery();
var table = LoadTable(otherTable.TableName);
Tables.Add(table);
return table;
}
/// <summary>
/// Replaces the table data with the data from another table.
/// </summary>
/// <param name="otherTable">The other table.</param>
public void ReplaceTableData(ILocalDataBase otherDB, DataTable otherTable)
{
var dropCommand = _connection.CreateCommand();
dropCommand.CommandText = String.Format("DELETE FROM {0};", otherTable.TableName);
dropCommand.ExecuteNonQuery();
var attacheCommand = _connection.CreateCommand();
attacheCommand.CommandText = String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source);
attacheCommand.ExecuteNonQuery();
var copyCommand = _connection.CreateCommand();
copyCommand.CommandText = String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other");
copyCommand.ExecuteNonQuery();
var detacheCommand = _connection.CreateCommand();
detacheCommand.CommandText = "DETACH other;";
detacheCommand.ExecuteNonQuery();
}
/// <summary>
/// Gets the SQL command for <see cref="ReplaceTableData(ILocalDataBase, DataTable)"/>.
/// </summary>
/// <param name="otherDB"></param>
/// <param name="otherTable">The other table.</param>
/// <returns></returns>
public string GetReplaceTableDataCommand(ILocalDataBase otherDB, DataTable otherTable)
{
String cmd = String.Format("DELETE FROM {0};", otherTable.TableName) + Environment.NewLine;
cmd += String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source) + Environment.NewLine;
cmd += String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other") + Environment.NewLine;
cmd += "DETACH other;" + Environment.NewLine;
return cmd;
}
/// <summary>
/// Gets the SQL command for <see cref="CloneTableFrom(ILocalDataBase, DataTable)" />.
/// </summary>
/// <param name="otherDB">The other database.</param>
/// <param name="otherTable">The other table.</param>
/// <returns></returns>
public String GetCloneTableFromCommand(ILocalDataBase otherDB, DataTable otherTable)
{
String cmd = String.Format("CREATE TABLE {0} (", otherTable.TableName);
foreach (DataColumn column in otherTable.Columns)
{
cmd += String.Format("{0} {1} {2} {3} {4} {5}",
column.ColumnName,
column.GetSQLType(),
otherTable.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
column.Unique ? "UNIQUE" : null,
column.IsNotNull() ? "NOT NULL" : null,
column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null)
+ ", " + Environment.NewLine;
}
cmd += ");";
cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
cmd += Environment.NewLine;
cmd += String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source);
cmd += Environment.NewLine;
cmd += String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other");
cmd += Environment.NewLine;
cmd += "DETACH other;";
return cmd;
}
/// <summary>
/// Adds the specified column to the specified table.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="column">The column.</param>
/// <returns></returns>
public DataColumn AddColumn(DataTable table, DataColumn column)
{
var insertCommand = _connection.CreateCommand();
insertCommand.CommandText = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} {3} {4} {5}",
table.TableName,
column.ColumnName,
column.GetSQLType(),
table.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
column.Unique ? "UNIQUE" : null,
//column.IsNotNull() ? "NOT NULL" : null,
column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null);
insertCommand.ExecuteNonQuery();
var t = LoadTable(table.TableName);
var index = Tables.IndexOf(Tables.Single(x => x.TableName == table.TableName));
Tables[index] = t;
return t.Columns[column.ColumnName];
}
/// <summary>
/// Gets the SQL command for <see cref="AddColumn(DataTable, DataColumn)" />.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="column">The column.</param>
/// <returns></returns>
public String GetAddColumnCommand(DataTable table, DataColumn column)
{
String cmd = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} {3} {4} {5}",
table.TableName,
column.ColumnName,
column.GetSQLType(),
table.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
column.Unique ? "UNIQUE" : null,
//column.IsNotNull() ? "NOT NULL" : null,
column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null);
return cmd;
}
/// <summary>
/// Adds the specified row to the specified table.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="row">The row.</param>
public void AddRow(DataTable table, DataRow row)
{
var insertCommand = _connection.CreateCommand();
List<String> values = new List<string>();
for (int i = 0; i < row.ItemArray.Length; i++)
{
String value = row.ItemArray[i].ToString();
double num = 0;
if (row.ItemArray[i].GetType() == typeof(bool))
{
value = ((bool)row.ItemArray[i]) ? 1.ToString() : 0.ToString();
}
if (row.ItemArray[i].GetType() == typeof(DateTime))
{
value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
}
if (!double.TryParse(value, out num))
{
value = "'" + value + "'";
}
values.Add(value);
}
insertCommand.CommandText = String.Format("INSERT INTO {0} VALUES({1});", table.TableName, String.Join(",", values));
insertCommand.ExecuteNonQuery();
var desRow = table.NewRow();
desRow.ItemArray = row.ItemArray.Clone() as object[];
}
/// <summary>
/// Gets the SQL command for <see cref="AddRow(DataTable, DataRow)" />.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="row">The row.</param>
/// <returns></returns>
public String GetAddRowCommand(DataTable table, DataRow row)
{
List<String> values = new List<string>();
for (int i = 0; i < row.ItemArray.Length; i++)
{
String value = row.ItemArray[i].ToString();
double num = 0;
if (row.ItemArray[i].GetType() == typeof(bool))
{
value = ((bool)row.ItemArray[i]) ? 1.ToString() : 0.ToString();
}
if (row.ItemArray[i].GetType() == typeof(DateTime))
{
value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
}
if (!double.TryParse(value, out num))
{
value = "'" + value + "'";
}
values.Add(value);
}
String cmd = String.Format("INSERT INTO {0} VALUES({1});", table.TableName, String.Join("," + Environment.NewLine, values));
return cmd;
}
/// <summary>
/// Updates the matching row by the row GUID.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="row">The row.</param>
public void UpdateRow(DataTable table, DataRow row)
{
var updateCommand = _connection.CreateCommand();
List<String> values = new List<string>();
for (int i = 0; i < row.ItemArray.Length; i++)
{
String value = row.ItemArray[i].ToString();
double num = 0;
if (row.ItemArray[i].GetType() == typeof(bool))
{
value = ((bool)row.ItemArray[i]) ? 1.ToString() : 0.ToString();
}
if (row.ItemArray[i].GetType() == typeof(DateTime))
{
value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
}
if (!double.TryParse(value, out num))
{
value = "'" + value + "'";
}
values.Add(value);
}
String cmd = String.Format("UPDATE {0} SET ", table.TableName);
String guid = String.Empty;
for (int columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++)
{
DataColumn column = table.Columns[columnIndex];
if (column.ColumnName == Constants.ID)
{
continue;
}
else if (column.ColumnName == Constants.GUID)
{
guid = values[columnIndex];
continue;
}
cmd += String.Format("{0} = {1},{2}", column.ColumnName, values[columnIndex], Environment.NewLine);
}
cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
cmd += "WHERE" + Environment.NewLine;
cmd += String.Format("{0} = {1};", Constants.GUID, guid);
updateCommand.CommandText = cmd;
updateCommand.ExecuteNonQuery();
var desRow = table.NewRow();
desRow.ItemArray = row.ItemArray.Clone() as object[];
}
/// <summary>
/// Gets the SQL command for <see cref="UpdateRow(DataTable, DataRow)" />.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="row">The row.</param>
/// <returns></returns>
public String GetUpdateRowCommand(DataTable table, DataRow row)
{
List<String> values = new List<string>();
for (int i = 0; i < row.ItemArray.Length; i++)
{
String value = row.ItemArray[i].ToString();
double num = 0;
if (row.ItemArray[i].GetType() == typeof(bool))
{
value = ((bool)row.ItemArray[i]) ? 1.ToString() : 0.ToString();
}
if (row.ItemArray[i].GetType() == typeof(DateTime))
{
value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
}
if (!double.TryParse(value, out num))
{
value = "'" + value + "'";
}
values.Add(value);
}
String cmd = String.Format("UPDATE {0} SET ", table.TableName);
String guid = String.Empty;
for (int columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++)
{
DataColumn column = table.Columns[columnIndex];
if (column.ColumnName == Constants.ID)
{
continue;
}
else if (column.ColumnName == Constants.GUID)
{
guid = values[columnIndex];
continue;
}
cmd += String.Format("{0} = {1},{2}", column.ColumnName, values[columnIndex], Environment.NewLine);
}
cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
cmd += "WHERE" + Environment.NewLine;
cmd += String.Format("{0} = {1};", Constants.GUID, guid);
return cmd;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
_connection.Close();
_connection.Dispose();
GC.Collect();
DateTime startTime = DateTime.Now;
while (startTime.AddSeconds(2) > DateTime.Now)
{
try
{
using (FileStream stream = File.Open(Source, FileMode.Open, FileAccess.Read))
{
return;
}
}
catch (IOException)
{
GC.Collect();
Thread.Sleep(200);
}
}
}
}
}
|