Fix [https://git.tompit.com/Connected/Connected.Host/issues/1] #1
@ -7,9 +7,9 @@ root = true
 | 
				
			|||||||
#### Core EditorConfig Options ####
 | 
					#### Core EditorConfig Options ####
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Indentation and spacing
 | 
					# Indentation and spacing
 | 
				
			||||||
indent_size = 4
 | 
					indent_size = 3
 | 
				
			||||||
indent_style = tab
 | 
					indent_style = tab
 | 
				
			||||||
tab_width = 4
 | 
					tab_width = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# New line preferences
 | 
					# New line preferences
 | 
				
			||||||
end_of_line = crlf
 | 
					end_of_line = crlf
 | 
				
			||||||
 | 
				
			|||||||
@ -1,61 +1,125 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
internal sealed class DataParameterCollection : List<IDbDataParameter>, IDataParameterCollection
 | 
					internal sealed class DataParameterCollection : DbParameterCollection
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public object this[string parameterName]
 | 
						private readonly object _syncRoot = new();
 | 
				
			||||||
 | 
						public DataParameterCollection()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		get
 | 
							Items = new();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private List<DbParameter> Items { get; }
 | 
				
			||||||
 | 
						public override int Count => Items.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override object SyncRoot => _syncRoot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override int Add(object value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (value is not DbParameter parameter)
 | 
				
			||||||
 | 
								throw new InvalidCastException(nameof(DbParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Items.Add(parameter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return Items.Count - 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void AddRange(Array values)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							foreach (var item in values)
 | 
				
			||||||
 | 
								Add(item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void Clear()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Items.Clear();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override bool Contains(object value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Items.Contains(value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override bool Contains(string value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Items.FirstOrDefault(f => string.Equals(f.ParameterName, value, StringComparison.OrdinalIgnoreCase)) is not null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void CopyTo(Array array, int index)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							foreach (var item in array)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			foreach (var parameter in this)
 | 
								Insert(index, item);
 | 
				
			||||||
			{
 | 
								index++;
 | 
				
			||||||
				if (string.Equals(parameter.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase))
 | 
					 | 
				
			||||||
					return parameter;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			throw new NullReferenceException(nameof(IDbDataParameter));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		set
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (value is not IDbDataParameter parameter)
 | 
					 | 
				
			||||||
				throw new InvalidCastException(nameof(IDbDataParameter));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var idx = IndexOf(parameterName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (idx < 0)
 | 
					 | 
				
			||||||
				throw new NullReferenceException(nameof(IDbDataParameter));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this[idx] = parameter;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool Contains(string parameterName)
 | 
						public override IEnumerator GetEnumerator()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		foreach (var parameter in this)
 | 
							return Items.GetEnumerator();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (string.Equals(parameter.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase))
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int IndexOf(string parameterName)
 | 
						public override int IndexOf(object value)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		for (var i = 0; i < Count; i++)
 | 
							if (value is not DbParameter parameter)
 | 
				
			||||||
		{
 | 
								throw new InvalidCastException(nameof(DbParameter));
 | 
				
			||||||
			var current = this[i];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (string.Equals(current.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase))
 | 
							return Items.IndexOf(parameter);
 | 
				
			||||||
				return i;
 | 
						}
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
						public override int IndexOf(string parameterName)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (Items.FirstOrDefault(f => string.Equals(f.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase)) is DbParameter parameter)
 | 
				
			||||||
 | 
								return Items.IndexOf(parameter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void RemoveAt(string parameterName)
 | 
						public override void Insert(int index, object value)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (this[parameterName] is IDbDataParameter target)
 | 
							if (value is not DbParameter parameter)
 | 
				
			||||||
			Remove(target);
 | 
								throw new InvalidCastException(nameof(DbParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Items.Insert(index, parameter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void Remove(object value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (value is not DbParameter parameter)
 | 
				
			||||||
 | 
								throw new InvalidCastException(nameof(DbParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Items.Remove(parameter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void RemoveAt(int index)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Items.RemoveAt(index);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void RemoveAt(string parameterName)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (Items.FirstOrDefault(f => string.Equals(f.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase)) is DbParameter parameter)
 | 
				
			||||||
 | 
								Items.Remove(parameter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected override DbParameter GetParameter(int index)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Items[index];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected override DbParameter GetParameter(string parameterName)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Items.First(f => string.Equals(f.ParameterName, parameterName, StringComparison.OrdinalIgnoreCase));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected override void SetParameter(int index, DbParameter value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Items[index] = value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected override void SetParameter(string parameterName, DbParameter value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Items[IndexOf(parameterName)] = value;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using Connected.ServiceModel.Client.Data.Remote;
 | 
					using Connected.ServiceModel.Client.Data.Remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
@ -18,6 +19,7 @@ internal sealed class TableConnection : IDbConnection
 | 
				
			|||||||
	/// <summary>
 | 
						/// <summary>
 | 
				
			||||||
	/// The connection string (URL) used when performing the requests. 
 | 
						/// The connection string (URL) used when performing the requests. 
 | 
				
			||||||
	/// </summary>
 | 
						/// </summary>
 | 
				
			||||||
 | 
						[AllowNull]
 | 
				
			||||||
	public string ConnectionString { get; set; }
 | 
						public string ConnectionString { get; set; }
 | 
				
			||||||
	/// <summary>
 | 
						/// <summary>
 | 
				
			||||||
	/// The request timeout in seconds.
 | 
						/// The request timeout in seconds.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,64 +1,96 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
using Connected.ServiceModel.Client.Data.Remote;
 | 
					using Connected.ServiceModel.Client.Data.Remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
internal sealed class TableDataCommand : IDbCommand
 | 
					internal sealed class TableDataCommand : DbCommand
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public TableDataCommand(RemoteTableService tables)
 | 
						public TableDataCommand(RemoteTableService tables)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Parameters = new DataParameterCollection();
 | 
							Parameters = new DataParameterCollection();
 | 
				
			||||||
		Tables = tables;
 | 
							Tables = tables;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	public string CommandText { get; set; }
 | 
					 | 
				
			||||||
	public int CommandTimeout { get; set; }
 | 
					 | 
				
			||||||
	public CommandType CommandType { get; set; }
 | 
					 | 
				
			||||||
	public IDbConnection? Connection { get; set; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public IDataParameterCollection Parameters { get; }
 | 
						public new DataParameterCollection Parameters { get; }
 | 
				
			||||||
 | 
					 | 
				
			||||||
	public IDbTransaction? Transaction { get; set; }
 | 
					 | 
				
			||||||
	public UpdateRowSource UpdatedRowSource { get; set; }
 | 
					 | 
				
			||||||
	public RemoteTableService Tables { get; }
 | 
						public RemoteTableService Tables { get; }
 | 
				
			||||||
 | 
						[AllowNull]
 | 
				
			||||||
 | 
						public override string CommandText { get; set; }
 | 
				
			||||||
 | 
						public override int CommandTimeout { get; set; } = 120;
 | 
				
			||||||
 | 
						public override CommandType CommandType { get; set; } = CommandType.Text;
 | 
				
			||||||
 | 
						protected override DbConnection? DbConnection { get; set; }
 | 
				
			||||||
 | 
						protected override DbParameterCollection DbParameterCollection => Parameters;
 | 
				
			||||||
 | 
						protected override DbTransaction? DbTransaction { get; set; }
 | 
				
			||||||
 | 
						public override bool DesignTimeVisible { get; set; }
 | 
				
			||||||
 | 
						public override UpdateRowSource UpdatedRowSource { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void Cancel()
 | 
						protected override DbParameter CreateDbParameter()
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public IDbDataParameter CreateParameter()
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return new TableDataParameter();
 | 
							return new TableDataParameter();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void Dispose()
 | 
						public override async Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							await Tables.Update(ParseCommandText());
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public int ExecuteNonQuery()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		AsyncUtils.RunSync(() => Tables.Update(CommandText));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public IDataReader ExecuteReader()
 | 
						public override int ExecuteNonQuery()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return new TableDataReader(AsyncUtils.RunSync(() => Tables.Query(CommandText)));
 | 
							AsyncUtils.RunSync(() => Tables.Update(ParseCommandText()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public IDataReader ExecuteReader(CommandBehavior behavior)
 | 
						protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return new TableDataReader(AsyncUtils.RunSync(() => Tables.Query(CommandText)));
 | 
							return new TableDataReader(await Tables.Query(ParseCommandText()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public object? ExecuteScalar()
 | 
						protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return new TableDataReader(AsyncUtils.RunSync(() => Tables.Query(ParseCommandText())));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void Prepare()
 | 
						private string ParseCommandText()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							var text = new StringBuilder(CommandText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							foreach (IDbDataParameter parameter in Parameters)
 | 
				
			||||||
 | 
								text = text.Replace(parameter.ParameterName, ParseValue(parameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return text.ToString();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static string? ParseValue(IDbDataParameter parameter)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (parameter.Value is null || parameter.Value == DBNull.Value)
 | 
				
			||||||
 | 
								return "null";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return parameter.DbType switch
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								DbType.AnsiString or DbType.String or DbType.AnsiStringFixedLength or DbType.StringFixedLength or DbType.Xml => $"'{parameter.Value}'",
 | 
				
			||||||
 | 
								_ => parameter.Value.ToString(),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void Cancel()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override object? ExecuteScalar()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							var reader = ExecuteReader();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (reader.Read())
 | 
				
			||||||
 | 
								return reader[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override void Prepare()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
using Connected.Annotations;
 | 
					using Connected.Annotations;
 | 
				
			||||||
using Connected.Data.Storage;
 | 
					using Connected.Data.Storage;
 | 
				
			||||||
using Connected.ServiceModel.Client.Data.Remote;
 | 
					using Connected.ServiceModel.Client.Data.Remote;
 | 
				
			||||||
using Microsoft.Data.SqlClient;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,7 +19,7 @@ internal sealed class TableDataConnection : DatabaseConnection
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		if (cmd.Parameters.Count > 0)
 | 
							if (cmd.Parameters.Count > 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			foreach (SqlParameter i in cmd.Parameters)
 | 
								foreach (DbParameter i in cmd.Parameters)
 | 
				
			||||||
				i.Value = DBNull.Value;
 | 
									i.Value = DBNull.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
@ -30,7 +30,7 @@ internal sealed class TableDataConnection : DatabaseConnection
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		foreach (var i in command.Operation.Parameters)
 | 
							foreach (var i in command.Operation.Parameters)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			cmd.Parameters.Add(new SqlParameter
 | 
								cmd.Parameters.Add(new TableDataParameter
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				ParameterName = i.Name,
 | 
									ParameterName = i.Name,
 | 
				
			||||||
				DbType = i.Type,
 | 
									DbType = i.Type,
 | 
				
			||||||
@ -39,17 +39,17 @@ internal sealed class TableDataConnection : DatabaseConnection
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected override object GetParameterValue(IDbCommand command, string parameterName)
 | 
						protected override object? GetParameterValue(IDbCommand command, string parameterName)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (command is SqlCommand cmd)
 | 
							if (command is TableDataCommand cmd)
 | 
				
			||||||
			return cmd.Parameters[parameterName].Value;
 | 
								return cmd.Parameters[parameterName].Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return null;
 | 
							return null;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected override void SetParameterValue(IDbCommand command, string parameterName, object value)
 | 
						protected override void SetParameterValue(IDbCommand command, string parameterName, object? value)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (command is SqlCommand cmd)
 | 
							if (command is TableDataCommand cmd)
 | 
				
			||||||
			cmd.Parameters[parameterName].Value = value;
 | 
								cmd.Parameters[parameterName].Value = value;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,20 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
internal class TableDataParameter : IDbDataParameter
 | 
					internal class TableDataParameter : DbParameter
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public byte Precision { get; set; }
 | 
						public override DbType DbType { get; set; }
 | 
				
			||||||
	public byte Scale { get; set; }
 | 
						public override ParameterDirection Direction { get; set; }
 | 
				
			||||||
	public int Size { get; set; }
 | 
						public override bool IsNullable { get; set; }
 | 
				
			||||||
	public DbType DbType { get; set; }
 | 
						public override string? ParameterName { get; set; }
 | 
				
			||||||
	public ParameterDirection Direction { get; set; }
 | 
						public override int Size { get; set; }
 | 
				
			||||||
	public bool IsNullable { get; set; }
 | 
						public override string? SourceColumn { get; set; }
 | 
				
			||||||
	public string ParameterName { get; set; }
 | 
						public override bool SourceColumnNullMapping { get; set; }
 | 
				
			||||||
	public string SourceColumn { get; set; }
 | 
						public override object? Value { get; set; }
 | 
				
			||||||
	public DataRowVersion SourceVersion { get; set; }
 | 
					
 | 
				
			||||||
	public object? Value { get; set; }
 | 
						public override void ResetDbType()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,164 +1,221 @@
 | 
				
			|||||||
using System.Data;
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
using System.Diagnostics.CodeAnalysis;
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Text.Json.Nodes;
 | 
					using System.Text.Json.Nodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Data;
 | 
					namespace Connected.ServiceModel.Client.Data;
 | 
				
			||||||
internal sealed class TableDataReader : IDataReader
 | 
					internal sealed class TableDataReader : DbDataReader
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public TableDataReader(JsonArray items)
 | 
						public TableDataReader(JsonArray items)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Items = items;
 | 
							Items = items;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public object this[int i] => throw new NotImplementedException();
 | 
						public override object this[int ordinal] => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public object this[string name] => throw new NotImplementedException();
 | 
						public override object this[string name] => throw new NotImplementedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int Depth => throw new NotImplementedException();
 | 
						private JsonArray Items { get; }
 | 
				
			||||||
 | 
						private int Index { get; set; } = -1;
 | 
				
			||||||
 | 
						private JsonObject? Current => Index < 0 ? null : Items[Index] as JsonObject;
 | 
				
			||||||
 | 
						public override int Depth => 1;
 | 
				
			||||||
 | 
						public override int FieldCount => Current is null ? 0 : Current.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool IsClosed => throw new NotImplementedException();
 | 
						public override bool HasRows => Items.Any();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int RecordsAffected => throw new NotImplementedException();
 | 
						public override bool IsClosed => false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int FieldCount => throw new NotImplementedException();
 | 
						public override int RecordsAffected => Items.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public JsonArray Items { get; }
 | 
						public override bool GetBoolean(int ordinal)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	public void Close()
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<bool>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void Dispose()
 | 
						public override byte GetByte(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<byte>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool GetBoolean(int i)
 | 
						public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							var value = GetValue<string>(ordinal);
 | 
				
			||||||
 | 
							var bytes = Convert.FromBase64String(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							buffer ??= new byte[bufferOffset + length];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = 0; i < length; i++)
 | 
				
			||||||
 | 
								buffer[bufferOffset + i] = bytes[dataOffset + i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return length;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public byte GetByte(int i)
 | 
						public override char GetChar(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<char>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public long GetBytes(int i, long fieldOffset, byte[]? buffer, int bufferoffset, int length)
 | 
						public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							var value = GetValue<string>(ordinal);
 | 
				
			||||||
 | 
							var bytes = Convert.FromBase64String(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							buffer ??= new char[bufferOffset + length];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = 0; i < length; i++)
 | 
				
			||||||
 | 
								buffer[bufferOffset + i] = (char)bytes[dataOffset + i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return length;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public char GetChar(int i)
 | 
						public override string GetDataTypeName(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							/*
 | 
				
			||||||
 | 
							 * TODO: resolve appropriate type
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return typeof(string).Name;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public long GetChars(int i, long fieldoffset, char[]? buffer, int bufferoffset, int length)
 | 
						public override DateTime GetDateTime(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<DateTime>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public IDataReader GetData(int i)
 | 
						public override decimal GetDecimal(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<decimal>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public string GetDataTypeName(int i)
 | 
						public override double GetDouble(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<double>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public DateTime GetDateTime(int i)
 | 
						public override IEnumerator GetEnumerator()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return Items.GetEnumerator();
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public decimal GetDecimal(int i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public double GetDouble(int i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		throw new NotImplementedException();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)]
 | 
						[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)]
 | 
				
			||||||
	public Type GetFieldType(int i)
 | 
						public override Type GetFieldType(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							/*
 | 
				
			||||||
 | 
							 * TODO: resolve appropriate type
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return typeof(string);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public float GetFloat(int i)
 | 
						public override float GetFloat(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<float>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public Guid GetGuid(int i)
 | 
						public override Guid GetGuid(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<Guid>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public short GetInt16(int i)
 | 
						public override short GetInt16(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<short>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int GetInt32(int i)
 | 
						public override int GetInt32(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<int>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public long GetInt64(int i)
 | 
						public override long GetInt64(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<long>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public string GetName(int i)
 | 
						public override string GetName(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							if (Current is null)
 | 
				
			||||||
 | 
								throw new NullReferenceException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (Current.ElementAt(ordinal).Key is string key)
 | 
				
			||||||
 | 
								return key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							throw new NullReferenceException();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int GetOrdinal(string name)
 | 
						public override int GetOrdinal(string name)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							if (Current is null)
 | 
				
			||||||
 | 
								throw new NullReferenceException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = 0; i < Current.Count; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (string.Equals(Current.ElementAt(i).Key, name, StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
									return i;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public DataTable? GetSchemaTable()
 | 
						public override string GetString(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<string>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public string GetString(int i)
 | 
						public override object GetValue(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return GetValue<object>(ordinal);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public object GetValue(int i)
 | 
						public override int GetValues(object[] values)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							if (Current is null)
 | 
				
			||||||
 | 
								throw new NullReferenceException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = 0; i < Current.Count; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var value = Current.ElementAt(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (value.Value is not null)
 | 
				
			||||||
 | 
									values[i] = value.Value.AsValue().GetValue<object>();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return Current.Count;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public int GetValues(object[] values)
 | 
						public override bool IsDBNull(int ordinal)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool IsDBNull(int i)
 | 
						public override bool NextResult()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool NextResult()
 | 
						public override bool Read()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		throw new NotImplementedException();
 | 
							if (Items.Count >= Index + 1)
 | 
				
			||||||
	}
 | 
							{
 | 
				
			||||||
 | 
								Index++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public bool Read()
 | 
								return true;
 | 
				
			||||||
	{
 | 
							}
 | 
				
			||||||
		//var items = AsyncUtils.RunSync(() => Service.Query(CommandText));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private T GetValue<T>(int ordinal)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return GetCurrentValue(ordinal).GetValue<T>();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private JsonValue GetCurrentValue(int ordinal)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (Current is null)
 | 
				
			||||||
 | 
								throw new NullReferenceException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (Current.ElementAt(ordinal).Value is not JsonValue value)
 | 
				
			||||||
 | 
								throw new NullReferenceException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ internal sealed class TableReader<T> : TableCommand, IStorageReader<T>
 | 
				
			|||||||
	public async Task<IDataReader> OpenReader()
 | 
						public async Task<IDataReader> OpenReader()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (Connection is null)
 | 
							if (Connection is null)
 | 
				
			||||||
			return default;
 | 
								throw new NullReferenceException(nameof(Connection));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return await Connection.OpenReader(this);
 | 
							return await Connection.OpenReader(this);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,9 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Connected.ServiceModel.Client.Net;
 | 
					namespace Connected.ServiceModel.Client.Net;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal sealed class SelectUrl : ServiceFunction<ConnectedServerUrlArgs, string>
 | 
					internal sealed class SelectUrl : ServiceFunction<ConnectedServerUrlArgs, string?>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	private const string Root = "https://localhost:61599";//"https://connected.tompit.com";
 | 
						private const string Root = "https://localhost:7069";//"https://connected.tompit.com";
 | 
				
			||||||
	protected override async Task<string?> OnInvoke()
 | 
						protected override async Task<string?> OnInvoke()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		await Task.CompletedTask;
 | 
							await Task.CompletedTask;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user