text: $C('$data.storageProviders.oData.oDataWhereCompiler', $data.Expressions.EntityExpressionVisitor, null, {
      constructor: function (provider, lambdaPrefix) {
          this.provider = provider;
          this.lambdaPrefix = lambdaPrefix;
      },
  
      compile: function (expression, context) {
          this.Visit(expression, context);
      },
  
      VisitParametricQueryExpression: function (expression, context) {
          this.Visit(expression.expression, context);
      },
  
      VisitUnaryExpression: function (expression, context) {
          context.data += expression.resolution.mapTo;
          context.data += "(";
          this.Visit(expression.operand, context);
          context.data += ")";
      },
  
  
      VisitSimpleBinaryExpression: function (expression, context) {
          context.data += "(";
          //TODO refactor!!!
          if (expression.nodeType == "in") {
              Guard.requireType("expression.right", expression.type, $data.Expressions.ConstantExpression);
              var paramValue = expression.right.value;
              if (!paramValue instanceof Array) { Guard.raise(new Exception("Right to the 'in' operator must be an array value")); }
              var result = null;
              var orResolution = { mapTo: "or", dataType: "boolean", name: "or" };
              var eqResolution = { mapTo: "eq", dataType: "boolean", name: "equal" };
  
              paramValue.forEach(function (item) {
                  var idValue = item;
                  var idCheck = Container.createSimpleBinaryExpression(expression.left, idValue,
                      $data.Expressions.ExpressionType.Equal, "==", "boolean", eqResolution);
                  if (result) {
                      result = Container.createSimpleBinaryExpression(result, idCheck,
                      $data.Expressions.ExpressionType.Or, "||", "boolean", orResolution);
                  } else {
                      result = idCheck;
                  };
              });
              var temp = context.data;
              context.data = '';
              this.Visit(result, context);
              context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');
          } else {
              this.Visit(expression.left, context);
              context.data += " ";
              context.data += expression.resolution.mapTo;
              context.data += " ";
              this.Visit(expression.right, context);
          };
          context.data += ")";
  
      },
  
      VisitEntityFieldExpression: function (expression, context) {
          this.Visit(expression.source, context);
          if (expression.source instanceof $data.Expressions.ComplexTypeExpression) {
              context.data += "/";
          }
          this.Visit(expression.selector, context);
      },
  
      VisitAssociationInfoExpression: function (expression, context) {
          context.data += expression.associationInfo.FromPropertyName;
      },
  
      VisitMemberInfoExpression: function (expression, context) {
          context.data += expression.memberName;
      },
  
      VisitQueryParameterExpression: function (expression, context) {
          var typeName = Container.resolveName(expression.type);
  
          var converter = this.provider.fieldConverter.toDb[typeName];
          var value = converter ? converter(expression.value) : expression.value;
  
          converter = this.provider.fieldConverter.escape[typeName];
          context.data += converter ? converter(value) : value;
      },
  
      VisitEntityFieldOperationExpression: function (expression, context) {
          Guard.requireType("expression.operation", expression.operation, $data.Expressions.MemberInfoExpression);
  
          //TODO refactor!
          var opDef = expression.operation.memberDefinition;
          var opName = opDef.mapTo || opDef.name;
          context.data += opName;
          context.data += "(";
          var paramCounter = 0;
          var params = opDef.parameters || [{ name: "@expression" }];
  
          var args = params.map(function (item, index) {
              if (item.name === "@expression") {
                  return expression.source;
              } else {
                  return expression.parameters[paramCounter++]
              };
          });
  
          args.forEach(function (arg, index) {
              if (index > 0) {
                  context.data += ",";
              };
              this.Visit(arg, context);
          }, this);
          context.data += ")";
      },
      VisitEntityFunctionOperationExpression: function (expression, context) {
          Guard.requireType("expression.operation", expression.operation, $data.Expressions.MemberInfoExpression);
          this.Visit(expression.source, context);
  
          //TODO refactor!
          var opDef = expression.operation.memberDefinition;
          var opName = opDef.mapTo || opDef.name;
          context.data += opName;
          context.data += "(";
          var paramCounter = 0;
          var params = opDef.method.params || [{ name: "@expression" }];
  
          var args = params.map(function (item, index) {
              if (item.name === "@expression") {
                  return expression.source;
              } else {
                  return expression.parameters[paramCounter++]
              };
          });
          var i = 0;
          args.forEach(function (arg, index) {
              if (arg === undefined || (arg instanceof $data.Expressions.ConstantExpression && typeof arg.value === 'undefined'))
                  return;
  
              if (i > 0) {
                  context.data += ",";
              };
              i++;
              context.data += params[index].name + '=';
              this.Visit(arg, context);
          }, this);
          context.data += ")";
      },
      VisitContextFunctionOperationExpression: function (expression, context) {
          return this.VisitEntityFunctionOperationExpression(expression, context);
      },
  
      VisitConstantExpression: function (expression, context) {
          var typeName = Container.resolveName(expression.type);
  
          var converter = this.provider.fieldConverter.toDb[typeName];
          var value = converter ? converter(expression.value) : expression.value;
  
          converter = this.provider.fieldConverter.escape[typeName];
          context.data += converter ? converter(value) : value;
      },
  
      VisitEntityExpression: function (expression, context) {
          this.Visit(expression.source, context);
  
          if (this.lambdaPrefix && expression.selector.lambda) {
              context.lambda = expression.selector.lambda;
              context.data += (expression.selector.lambda + '/');
          }
  
          //if (expression.selector instanceof $data.Expressions.EntityExpression) {
          //    this.Visit(expression.selector, context);
          //}
      },
  
      VisitEntitySetExpression: function (expression, context) {
          this.Visit(expression.source, context);
          if (expression.selector instanceof $data.Expressions.AssociationInfoExpression) {
              this.Visit(expression.selector, context);
              context.data += "/";
          }
      },
  
      VisitFrameOperationExpression: function (expression, context) {
          this.Visit(expression.source, context);
  
          Guard.requireType("expression.operation", expression.operation, $data.Expressions.MemberInfoExpression);
  
          //TODO refactor!
          var opDef = expression.operation.memberDefinition;
          var opName = opDef.mapTo || opDef.name;
          context.data += opName;
          context.data += "(";
          var paramCounter = 0;
          var params = opDef.parameters || [{ name: "@expression" }];
  
          var args = params.map(function (item, index) {
              if (item.name === "@expression") {
                  return expression.source;
              } else {
                  return expression.parameters[paramCounter++]
              };
          });
  
          for (var i = 0; i < args.length; i++) {
              var arg = args[i];
              if (arg && arg.value instanceof $data.Queryable) {
                  var frameExpression = new opDef.frameType(arg.value.expression);
                  var preparator = Container.createQueryExpressionCreator(arg.value.entityContext);
                  var prep_expression = preparator.Visit(frameExpression);
  
                  var compiler = new $data.storageProviders.oData.oDataWhereCompiler(this.provider, true);
                  var frameContext = { data: "" };
                  var compiled = compiler.compile(prep_expression, frameContext);
  
                  context.data += (frameContext.lambda + ': ' + frameContext.data);
              };
          }
          context.data += ")";
      }
  });