Есть необходимость привязать возможность использования SQL запросов для "работы" с данными в приложении на C#.
Данные лежат в памяти приложения в виде POCO объектов в списках, словарях и остальных ICollection'ах.
Нашёл библиотеку
sql-dotnet которая:
- Парсит SQL и гренерирует Execution plan в виде IL-like кода
- SQLRuntime который выполняет IL-like код вызывая пользовательскую реализацию IQueryExecutor'а
- Интерфейс IQueryExecutor, реализуя который мы "предоставляем" доступ к данным
Данная библиотека достаточно сырая и не поддерживает много чего из ANSI SQL, но допилить можно.
Скриншот фрагмента кода удалён модератором.
Реализация IQueryExecutor:
internal class Executor : IQueryExecutor
{
private void AssertFunction(string name, IList<QueryParameter> parameter, int minParameter, int maxParameter, DataType[] types)
{
if (parameter.Count > maxParameter || parameter.Count < minParameter)
{
throw new ArgumentException(string.Format("`{0}` expected at least {1} parameter.", name, minParameter));
}
}
public Tuple<object, DataType> CallFunction(string name, IList<QueryParameter> parameter)
{
name = name.ToLower();
if (!string.IsNullOrWhiteSpace(name))
{
switch (name)
{
#region [Concat]
case "concat":
{
if (parameter == null || parameter.Count < 1)
{
throw new ArgumentException("`Concat` requires atleast one argument.");
}
StringBuilder sb = new StringBuilder();
foreach (var p in parameter)
{
sb.Append(p.Value);
}
return new Tuple<object, DataType>(sb.ToString(), DataType.Str);
}
#endregion
#region [newid]
case "newid":
{
AssertFunction(name, parameter, 0, 0, new DataType[] { });
return new Tuple<object, DataType>(Guid.NewGuid(), DataType.Object);
}
#endregion
}
}
throw new Exception("Could not find function " + name ?? "--noname--");
}
public TableDefinition GetTableSchema(string owner, string table) { ... }
public int Insert(string tableName, IList<string> columns, IList<QueryParameter> parameter) { ... }
public IList<QueryResultRow> Select(string tableName, bool isScalar, bool distinctValues, IList<ColumnDefinition> columns, FilterCursorCCNode filter, Scope parameter)
{
var returnValue = new List<QueryResultRow>();
var row = new QueryResultRow();
row.Columns.Add("archiv_guid", Guid.NewGuid());
row.Columns.Add("archiv_blob", new byte[] { 1, 23, 213, 24 });
returnValue.Add(row);
return returnValue;
}
}
Вопрос: Существует ли более зрелое подобное решение, которое позволит прикрутить SQL к своему проекту?