Я использую ServiceStack ORMLite и необходимо выполнить запрос, например ниже:Как использовать подзапросы в ServiceStack ORMLite
SqlServerExpressionVisitor<Contact> sql = new SqlServerExpressionVisitor<Contact>();
SqlServerExpressionVisitor<Account> accSql = new SqlServerExpressionVisitor<Account>();
var finalSql = sql.Where(a=>
(from a1 in accSql where a1.Type == "Client"
&& a1.Id==a.AccountId select a1).Any());
Когда выполнить этот запрос, я получаю ошибку лямбда «а» не определен в рамках , «a» здесь ссылка на переменную, определенную для вызова метода Where.
Как я могу использовать ExpressionVisitor для выполнения подзапросов в предложении WHERE?
UPDATE: Я создал свой собственный SqlServiceExpressionVisitor, который позволяет мне настроить, как ORM генерирует SQL-запросы. Я также добавил класс, например, как показано ниже:
public static class SQL
{
public static bool ExistsIn<T>(T Value, string subquery, params T[] parameters)
{
return true;
}
public static bool ExistsIn<T, TItem>(T Value, SqlExpressionVisitor<TItem> innerSql)
{
return true;
}
public static SqlExpressionVisitor<T> Linq<T>()
{
return OrmLiteConfig.DialectProvider.ExpressionVisitor<T>();
}
}
Затем продлил VisitMethodCall взять мой новый класс во внимание и вызвать мой пользовательский метод соответственно:
internal object VisitSQLMethodCall(MethodCallExpression m)
{
string methodName = m.Method.Name;
if (methodName == "ExistsIn")
{
string quotedColName = Visit(m.Arguments[0] as Expression).ToString();
dynamic visit = Visit(m.Arguments[1]);
string innerQuery = (visit is string) ? visit.ToString().Trim('"') : visit.ToSelectStatement();
if (m.Arguments[2] != null)
{
List<object> fields = VisitExpressionList((m.Arguments[2] as NewArrayExpression).Expressions);
int count = 0;
foreach (var field in fields)
{
innerQuery = innerQuery.Replace("@" + count.ToString(), field.ToString());
count++;
}
}
return new PartialSqlString(string.Format("{0} IN ({1})", quotedColName, innerQuery));
}
}
Результаты являются весьма многообещающими, вот как он может быть использован:
.Where(a => SQL.ExistsIn(a.AccountId, SQL.Linq<Account>()
.Where(acc => acc.Name.Contains("a")).Select(acc => acc.Id)))
Над создает подходящий внутренний SQL, однако, если я включать ссылку из родительского запроса, A получить системные вызовы return Expression.Lambda (m) .Compile(). DynamicInvoke(); которые производят ту же ошибку!
SQL.Linq<Contact>().Where(a => SQL.ExistsIn(a.AccountId, SQL.Linq<Account>()
.Where(acc => acc.Id == a.AccountId).Select(acc => acc.Id)))
Приведенное выше генерирует ошибку: параметр «a» не определен в области видимости. Я предполагаю, что мне нужно лишь каким-то образом добавить определение параметра ко второму вызову посещения в моем пользовательском методе, но я еще не понял, как это сделать! Любая помощь приветствуется!
Хотя я знаю ORMLite новой версии может обрабатывать соединения, я предпочел бы использовать другой ORM, такие как Dapper решить объединение между двумя или более таблицами. Я считаю Dapper более сильным в этой части. – coffekid
Я не видел никакой документации по Dapper, которая поддерживала бы Linq to SQL. Также я чувствую, что лучше понимаю код ORMLite, и он написан очень красиво. – sam360