public override void Translate( MethodCallExpression m, TranslationState state, UniqueNameGenerator nameGenerator) { var dbSelect = state.ResultStack.Peek() as IDbSelect; if (dbSelect != null) { dbSelect.Selection.IsDistinct = true; } var caller = m.GetCaller(); var entityInfo = caller.NodeType == ExpressionType.MemberAccess ? this._infoProvider.FindEntityInfo(caller.Type) : null; // if the caller of the Distinct function is a Entity // We need to add its primary keys into the query so that the result // of distinct is correct. Otherwise, it will only distinct on join keys if (entityInfo != null) { foreach (var pk in entityInfo.Keys) { var pkColumn = _dbFactory.BuildColumn(dbSelect.GetReturnEntityRef(), pk.DbName, pk.ValType); dbSelect.Selection.Add(pkColumn); } } }
/// <summary> Translate to SQL </summary> public override void Translate( MethodCallExpression m, TranslationState state, UniqueNameGenerator nameGenerator) { var dbExpression = GetAggregationTarget(m, state); IDbSelect childSelect = null; if (!m.GetCaller().Type.IsGrouping()) { childSelect = state.ResultStack.Pop() as IDbSelect; } // if the aggregation does not have expression, it means // the caller of the aggregation method must be a Select method call // In this case, the actual expression that we need to aggregate on, // will be inside the child select statement if (dbExpression == null && childSelect != null) { // to get the actual expression, we need to first unwrap the child select // because the translation of Select call always wrap the actual select childSelect = (IDbSelect)childSelect.From.Referee; dbExpression = childSelect.Selection.Last( s => string.IsNullOrEmpty(s.Alias) || !s.Alias.EndsWith(TranslationConstants.JoinKeySuffix)); childSelect.Selection.Remove(dbExpression); childSelect.GroupBys.Remove(dbExpression); } if (dbExpression == null) { throw new NotSupportedException("Can not aggregate."); } if (!(dbExpression is IDistinctable)) { throw new NotSupportedException("Expression must be Distinctable"); } var distinctable = (IDistinctable)dbExpression; distinctable.IsDistinct = true; var dbFunc = _dbFactory.BuildFunc("count", true, m.Method.ReturnType, dbExpression); CreateAggregation(m, state, nameGenerator, childSelect, dbFunc); }
public override void Translate( MethodCallExpression m, TranslationState state, UniqueNameGenerator nameGenerator) { var predicate = BuildCondition(m, state); IDbSelect childSelect = null; if (!m.GetCaller().Type.IsGrouping()) { childSelect = state.ResultStack.Pop() as IDbSelect; } var dbCountFunc = _dbFactory.BuildFunc(m.Method.Name.ToLower(), true, m.Method.ReturnType, predicate); CreateAggregation(m, state, nameGenerator, childSelect, dbCountFunc); }
protected override Expression VisitMethodCall(MethodCallExpression m) { var caller = m.GetCaller(); var args = m.GetArguments(); Visit(caller); // remove unneed DbReference from stack, this is a side effect of translation of the caller // we need to translate the caller to have the required select on the stack // but we dont neeed other thing that come with it, such as the DbReference while (_state.ResultStack.Count > 0 && _state.ResultStack.Peek() is DbReference) { _state.ResultStack.Pop(); } VistMethodArguments(args); if (!_plugIns.TranslateMethodCall(m, _state, _nameGenerator)) { throw new NotSupportedException(); } return(m); }
public static Expression[] GetArguments(this MethodCallExpression m) { var caller = m.GetCaller(); return(m.Arguments.Where(a => a != caller).ToArray()); }