From 9c24b5989bf41d3348c2b066857a21c687766e7a Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 9 Feb 2012 09:41:51 -0800 Subject: [PATCH] Log Grid added, using server side filtering, sorting and paging. Using DynamicQueryable. --- .../NzbDrone.Services.Service/Web.config | 6 +- .../RegisterDataTablesModelBinder.cs | 15 + NzbDrone.Web/Controllers/LogController.cs | 58 +- NzbDrone.Web/Dynamic Expressions.html | 2279 +++++++++++++++++ NzbDrone.Web/Helpers/DataTablesModelBinder.cs | 40 + NzbDrone.Web/Models/DataTablesParams.cs | 34 + NzbDrone.Web/Models/LogModel.cs | 19 + NzbDrone.Web/NzbDrone.Web.csproj | 9 + NzbDrone.Web/Views/History/Index.cshtml | 8 +- NzbDrone.Web/Views/Log/Index.cshtml | 133 +- NzbDrone.Web/Views/Log/IndexOld.cshtml | 65 + NzbDrone.Web/Views/Missing/Index.cshtml | 4 +- NzbDrone.Web/packages.config | 1 + .../DynamicQuery.1.0/DynamicQuery.1.0.nupkg | Bin 0 -> 46343 bytes .../content/Dynamic Expressions.html | 2279 +++++++++++++++++ packages/DynamicQuery.1.0/lib/35/Dynamic.dll | Bin 0 -> 46080 bytes 16 files changed, 4886 insertions(+), 64 deletions(-) create mode 100644 NzbDrone.Web/App_Start/RegisterDataTablesModelBinder.cs create mode 100644 NzbDrone.Web/Dynamic Expressions.html create mode 100644 NzbDrone.Web/Helpers/DataTablesModelBinder.cs create mode 100644 NzbDrone.Web/Models/DataTablesParams.cs create mode 100644 NzbDrone.Web/Models/LogModel.cs create mode 100644 NzbDrone.Web/Views/Log/IndexOld.cshtml create mode 100644 packages/DynamicQuery.1.0/DynamicQuery.1.0.nupkg create mode 100644 packages/DynamicQuery.1.0/content/Dynamic Expressions.html create mode 100644 packages/DynamicQuery.1.0/lib/35/Dynamic.dll diff --git a/NzbDrone.Services/NzbDrone.Services.Service/Web.config b/NzbDrone.Services/NzbDrone.Services.Service/Web.config index eece4679f..e6572f212 100644 --- a/NzbDrone.Services/NzbDrone.Services.Service/Web.config +++ b/NzbDrone.Services/NzbDrone.Services.Service/Web.config @@ -21,7 +21,7 @@ - + @@ -34,8 +34,8 @@ - - + + diff --git a/NzbDrone.Web/App_Start/RegisterDataTablesModelBinder.cs b/NzbDrone.Web/App_Start/RegisterDataTablesModelBinder.cs new file mode 100644 index 000000000..cd2d24690 --- /dev/null +++ b/NzbDrone.Web/App_Start/RegisterDataTablesModelBinder.cs @@ -0,0 +1,15 @@ +using System.Web.Mvc; +using System.Web.WebPages; +using NzbDrone.Web.Helpers; +using NzbDrone.Web.Models; + +[assembly: WebActivator.PreApplicationStartMethod(typeof(NzbDrone.Web.App_Start.RegisterDatatablesModelBinder), "Start")] + +namespace NzbDrone.Web.App_Start { + public static class RegisterDatatablesModelBinder { + public static void Start() { + if (!ModelBinders.Binders.ContainsKey(typeof(DataTablesParams))) + ModelBinders.Binders.Add(typeof(DataTablesParams), new DataTablesModelBinder()); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/LogController.cs b/NzbDrone.Web/Controllers/LogController.cs index d25c76819..0f3b80eb3 100644 --- a/NzbDrone.Web/Controllers/LogController.cs +++ b/NzbDrone.Web/Controllers/LogController.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic; using System.Text; using System.Web.Mvc; using NzbDrone.Common; @@ -26,6 +29,11 @@ namespace NzbDrone.Web.Controllers return View(); } + public ActionResult IndexOld() + { + return View(); + } + public FileContentResult File() { string log = string.Empty; @@ -47,8 +55,56 @@ namespace NzbDrone.Web.Controllers return JsonNotificationResult.Info("Logs Cleared"); } + public ActionResult AjaxBinding(DataTablesParams dataTablesParams) + { + var logs = _logProvider.GetAllLogs(); + var totalCount = logs.Count(); + + IQueryable q = logs; + if (!string.IsNullOrEmpty(dataTablesParams.sSearch)) + { + q = q.Where(b => b.Logger.Contains(dataTablesParams.sSearch) + || b.Exception.Contains(dataTablesParams.sSearch) + || b.Message.Contains(dataTablesParams.sSearch)); + } + + int filteredCount = q.Count(); + + int sortCol = dataTablesParams.iSortCol.First(); + var sortColName = sortCol == 0 ? "Time" : sortCol == 1 ? "Level" : "Logger"; + var sortExpression = String.Format("{0} {1}", sortColName, dataTablesParams.sSortDir.First()); + + var sorted = q.OrderBy(sortExpression); + + IQueryable filteredAndSorted = sorted; + if (filteredCount > dataTablesParams.iDisplayLength) + { + filteredAndSorted = sorted.Skip(dataTablesParams.iDisplayStart).Take(dataTablesParams.iDisplayLength); + } + + var logModels = filteredAndSorted.ToList().Select(s => new LogModel + { + Time = s.Time.ToString(), + Level = s.Level, + Source = s.Logger, + Message = s.Message, + Method = s.Method, + ExceptionType = s.ExceptionType, + Exception = s.Exception + }); + + return Json(new + { + sEcho = dataTablesParams.sEcho, + iTotalRecords = totalCount, + iTotalDisplayRecords = filteredCount, + aaData = logModels + }, + JsonRequestBehavior.AllowGet); + } + [GridAction] - public ActionResult AjaxBinding() + public ActionResult AjaxBindingOld() { return View(new GridModel(_logProvider.GetAllLogs())); } diff --git a/NzbDrone.Web/Dynamic Expressions.html b/NzbDrone.Web/Dynamic Expressions.html new file mode 100644 index 000000000..3735c922d --- /dev/null +++ b/NzbDrone.Web/Dynamic Expressions.html @@ -0,0 +1,2279 @@ + + + + + + + + +Dynamic Expression API + + + + + + + + + +
+ +

Dynamic Expressions +and Queries in LINQ

+ +

Database applications frequently rely on “Dynamic +SQL”—queries that are constructed at run-time through program logic. The LINQ +infrastructure supports similar capabilities through dynamic construction of +expression trees using the classes in the System.Linq.Expressions namespace. Expression +trees are an appropriate abstraction for a variety of scenarios, but for others +a string-based representation may be more convenient. The Dynamic Expression API extends the core +LINQ API with that capability. The API is located in the Dynamic.cs +source file and provides

+ +

·         +Dynamic parsing of strings to produce +expression trees (the ParseLambda +and Parse methods),

+ +

·         +Dynamic creation of “Data Classes” (the CreateClass methods), +and

+ +

·         +Dynamic string-based querying through LINQ +providers (the IQueryable extension +methods).

+ +

The Dynamic Expression API relies on a simple expression language for formulating +expressions and queries in strings.

+ +

Dynamic Expression API

+ +

The Dynamic +Expression API is brought into scope by using (importing) the System.Linq.Dynamic +namespace. Below is an example of applying the Dynamic Expression API to a LINQ +to SQL data source.

+ +

var +query =
+    db.Customers.
+    Where("City += @0 and Orders.Count >= @1", "London", 10).
+    OrderBy("CompanyName").
+    Select("new(CompanyName as Name, Phone)");

+ +

Note that expressions in the query are strings that could +have been dynamically constructed at run-time.

+ +

The ParseLambda Methods

+ +

The System.Linq.Dynamic.DynamicExpression +class defines the following overloaded ParseLambda methods for dynamically parsing +and creating lambda expressions.

+ +

public static LambdaExpression ParseLambda(
+    ParameterExpression[] +parameters, Type resultType,
+    string expression, params object[] values);

+ +

public static LambdaExpression ParseLambda(
+    Type argumentType, +Type resultType,
+    string expression, params object[] values);

+ +

public static Expression<Func<TArgument, +TResult>>
+    ParseLambda<TArgument, +TResult>(
+        string +expression, params object[] values);

+ +

The first ParseLambda overload parses a lambda +expression with the given parameters and expression body and returns an Expression<Func<…>> +instance representing the result. If the resultType parameter is non-null it specifies +the required result type for the expression. The values +parameter supplies zero or more substitution +values that may be referenced in the expression.

+ +

The example

+ +

ParameterExpression +x = Expression.Parameter(typeof(int), "x");
+ParameterExpression +y = Expression.Parameter(typeof(int), "y");
+LambdaExpression e += DynamicExpression.ParseLambda(
+    new ParameterExpression[] { x, y }, null, "(x + y) * +2");

+ +

creates and assigns an Expression<Func<int, int, int>> +instance to e representing the expression (x + y) * 2. If a required result type is specified, as in

+ +

LambdaExpression +e = DynamicExpression.ParseLambda(
+    new ParameterExpression[] { x, y }, typeof(double), "(x + y) * +2");

+ +

the parsing operation will include +an implicit conversion to the given result type, in +this case yielding an Expression<Func<int, int, +double>> instance.

+ +

The second ParseLambda overload parses a lambda +expression with a single unnamed parameter of a specified argumentType. This method corresponds to +calling the first ParseLambda overload with a parameters argument containing a single ParameterExpression with an +empty or null Name property.

+ +

­When parsing a lambda expression with a single unnamed +parameter, the members of the unnamed parameter are automatically in scope in +the expression string, and the current instance +given by the unnamed parameter can be referenced in whole using the keyword it. The example

+ +

LambdaExpression +e = DynamicExpression.ParseLambda(
+    typeof(Customer), typeof(bool),
+    "City = @0 and Orders.Count >= @1",
+    "London", 10);

+ +

creates and assigns an Expression<Func<Customer, bool>> instance to e. +Note that City and Orders +are members of Customer that are automatically +in scope. Also note the use of substitution +values to supply the constant values "London" +and 10.

+ +

The third ParseLambda overload is a genericly +typed version of the second overload. The example below produces the same Expression<Func<Customer, bool>> instance as the example above, but is +statically typed to that exact type.

+ +

Expression<Func<Customer, bool>> e =
+    DynamicExpression.ParseLambda<Customer, bool>(
+        "City += @0 and Orders.Count >= @1",
+        "London", +10);

+ +

The +Parse Method

+ +

The System.Linq.Dynamic.DynamicExpression +class defines the following method for parsing and creating expression tree +fragments.

+ +

public static Expression +Parse(Type resultType, +string expression,
+    params +object[] values);

+ +

The Parse method parses the given expression +and returns an expression tree. If the resultType parameter is non-null it specifies +the required result type of the expression. The values +parameter supplies zero or more substitution +values that may be referenced in the expression.

+ +

Unlike the ParseLambda +methods, the Parse method returns an “unbound” +expression tree fragment. The following example uses Parse to produce the same result as a previous example:

+ +

ParameterExpression +x = Expression.Parameter(typeof(int), "x");
+ParameterExpression +y = Expression.Parameter(typeof(int), "y");
+Dictionary<string, +object> symbols = new +Dictionary<string, +object>();
+symbols.Add("x", +x);
+symbols.Add("y", +y);
+Expression body = DynamicExpression.Parse(null, "(x + y) * +2", symbols);
+LambdaExpression e += Expression.Lambda(
+    body, new ParameterExpression[] { +x, y });

+ +

Note the use of a Dictionary<string, +object> to provide a dictionary of named substitution values that can be referenced in +the expression.

+ +

Substitution Values

+ +

Several methods in the Dynamic Expression API permit substitution values to +be specified through a parameter array. Substitution values are referenced in +an expression using identifiers of the form @x, where x is an +index into the parameter array. The last element of the parameter array may be +an object that implements IDictionary<string, object>. If so, this dictionary is +used to map identifiers to substitution values during parsing.

+ +

An identifier that references a substitution value is +processed as follows:

+ +

·         +If the value is of type System.Linq.Expressions.LambdaExpression, the +identifier must occur as part of a dynamic +lambda invocation. This allows composition of dynamic lambda expressions.

+ +

·         +Otherwise, if the value is of type System.Linq.Expressions.Expression, the given +expression is substituted for the identifier.

+ +

·         +Otherwise, the Expression.Constant method is used to create a constant expression from +the value which is then substituted for the identifier.

+ +

Dynamic Data Classes

+ +

A data class is a class that contains only data members. The +System.Linq.Dynamic.DynamicExpression +class defines the following methods for dynamically creating data classes.

+ +

public static Type CreateClass(params +DynamicProperty[] +properties);

+ +

public static Type CreateClass(IEnumerable<DynamicProperty> +properties);

+ +

The CreateClass +method creates a new data class with a given set of public properties and +returns the System.Type +object for the newly created class. If a data class with an identical sequence +of properties has already been created, the System.Type object for this class is returned.

+ +

Data classes implement private instance variables and +read/write property accessors for the specified +properties. Data classes also override the Equals +and GetHashCode +members to implement by-value equality.

+ +

Data classes are created in an in-memory assembly in the +current application domain. All data classes inherit from System.Linq.Dynamic.DynamicClass and are given +automatically generated names that should be considered private (the names will +be unique within the application domain but not across multiple invocations of +the application). Note that once created, a data class stays in memory for the +lifetime of the current application domain. There is currently no way to unload +a dynamically created data class.

+ +

The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers. This +feature in turn is often used with the dynamic Select +method to create projections.

+ +

The example below uses CreateClass to create a data class with two +properties, Name and Birthday, +and then uses .NET reflection to create an instance of the class and assign +values to the properties.

+ +

DynamicProperty[] +props = new DynamicProperty[] {
+    new DynamicProperty("Name", +typeof(string)),
+    new DynamicProperty("Birthday", +typeof(DateTime)) };
+Type type = DynamicExpression.CreateClass(props);
+object obj = Activator.CreateInstance(type);
+t.GetProperty("Name").SetValue(obj, "Albert", null);
+t.GetProperty("Birthday").SetValue(obj, new DateTime(1879, +3, 14), null);
+Console.WriteLine(obj);

+ +

IQueryable Extension Methods

+ +

The System.Linq.Dynamic.DynamicQueryable +class implements the following extension methods for dynamically querying +objects that implement the IQueryable<T> +interface.

+ +

public static IQueryable +Where(this IQueryable +source,
+    string predicate, params object[] values);

+ +

public static IQueryable<T> +Where<T>(this IQueryable<T> +source,
+    string predicate, params object[] values);

+ +

public static IQueryable +Select(this IQueryable +source,
+    string selector, params object[] values);

+ +

public static IQueryable OrderBy(this IQueryable source,
+    string ordering, params object[] values);

+ +

public static IQueryable<T> +OrderBy<T>(this +IQueryable<T> source,
+    string ordering, params object[] values);

+ +

public static IQueryable +Take(this IQueryable +source, int count);

+ +

public static IQueryable +Skip(this IQueryable +source, int count);

+ +

public static IQueryable GroupBy(this IQueryable source,
+    string keySelector, +string elementSelector, +params object[] values);

+ +

public static bool +Any(this IQueryable +source);

+ +

public static int +Count(this IQueryable +source);

+ +

These methods correspond to their System.Linq.Queryable counterparts, except +that they operate on IQueryable instead of IQueryable<T> and use strings instead of lambda +expressions to express predicates, selectors, and orderings. IQueryable is the non-generic base interface for IQueryable<T>, so the methods can be used even +when T isn’t known on beforehand, i.e. when the +source of a query is dynamically determined. (Note that because a dynamic +predicate or ordering does not affect the result type, generic overloads are +provided for Where and OrderBy in order to preserve strong typing +when possible.)

+ +

The predicate, selector, ordering, keySelector, and elementSelector parameters +are strings containing expressions written in the expression language. In the expression +strings, the members of the current instance +are automatically in scope and the instance itself can be referenced using the +keyword it.

+ +

The OrderBy +method permits a sequence of orderings to be specified, separated by commas. +Each ordering may optionally be followed by asc or ascending +to indicate ascending order, or desc or descending +to indicate descending order. The default order is ascending. The example

+ +

products.OrderBy("Category.CategoryName, +UnitPrice descending");

+ +

orders a sequence of products by +ascending category name and, within each category, descending unit price.

+ +

The ParseException Class

+ +

The Dynamic Expression API reports parsing errors using the System.Linq.Dynamic.ParseException +class. The Position property of the ParseException class gives +the character index in the expression string at which the parsing error +occurred.

+ +

Expression Language

+ +

The expression language implemented by the Dynamic +Expression API provides a simple and convenient way of writing expressions that +can be parsed into LINQ expression trees. The language supports most of the +constructs of expression trees, but it is by no means a complete query or +programming language. In particular, the expression language does not support +statements or declarations.

+ +

The expression language is designed to be familiar to C#, +VB, and SQL users. For this reason, some operators are present in multiple +forms, such as && and and.

+ +

Identifiers

+ +

An Identifier consists of a letter or underscore followed by +any number of letters, digits, or underscores. In order to reference an +identifier with the same spelling as a keyword, the identifier must be prefixed +with a single @ character. Some examples of identifiers:

+ +

x   Hello   +m_1   @true   @String

+ +

Identifiers of the from @x, where x is an integral number +greater than or equal to zero, are used to denote the substitution values, if any, that were passed +to the expression parser. For example:

+ +

customers.Where("Country = @0", +country);

+ +

Casing is not significant in identifiers or keywords.

+ +

Literals

+ +

The expression language supports integer, real, string, and +character literals.

+ +

An integer +literal consists of a sequence of digits. The type of an integer +literal is the first of the types Int32, UInt32, Int64, or UInt64 that can represent the given value. An integer +literal implicitly converts to any other numeric type +provided the number is in the range of that type. Some examples of integer +literals:

+ +

0   123   10000

+ +

A real +literal consists of an integral part followed by a fractional part +and/or an exponent. The integral part is a sequence of one or more digits. The +fractional part is a decimal point followed by one or more digits. The exponent +is the letter e or E +followed by an optional + or sign followed by one or more digits. The type of a +real literal is Double. +A real literal implicitly converts to any other real type +provided the number is in the range of that type. Some examples of real +literals:

+ +

1.0   2.25   10000.0   +1e0   1e10   1.2345E-4

+ +

A string +literal consists of zero or more characters enclosed in double +quotes. Inside a string literal, a double quote is written as two consecutive +double quotes. The type of a string literal is String. +Some examples of string literals:

+ +

"hello"   +""    +"""quoted"""   "'"

+ +

A character +literal consists of a single character enclosed in single quotes. +Inside a character literal, a single quote is written as two consecutive single +quotes. The type of a character literal is Char. +Some examples of character literals:

+ +

'A'   '1'   ''''   '"'

+ +

Constants

+ +

The predefined constants true +and false denote the two values of the type Boolean.

+ +

The predefined constant null +denotes a null reference. The null constant is +of type Object, but is also implicitly +convertible to any reference type.

+ +

Types

+ +

The expression language defines the following primitive types:

+ +

Object                +Boolean             +Char                     +String                +SByte                   +Byte
+Int16                   +UInt16                +Int32                   +UInt32                +Int64                   +UInt64
+Decimal     Single                +Double                +DateTime           +TimeSpan           +Guid

+ +

The primitive types correspond to the similarly named types +in the System namespace of the .NET Framework Base Class Library. The +expression language also defines a set of accessible +types consisting of the primitive types and the following types +from the System namespace:

+ +

Math                     +Convert

+ +

The accessible types are the only types that can be +explicitly referenced in expressions, and method invocations in the expression +language are restricted to methods declared in the accessible types.

+ +

The nullable form of a value type is +referenced by writing a ? +after the type name. For example, Int32? denotes the nullable form of Int32.

+ +

The non-nullable +and nullable forms of the types SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, and UInt64 are +collectively called the integral +types.

+ +

The non-nullable and nullable forms of +the types Single, Double, +and Decimal are collectively called the real types.

+ +

The integral types and real types +are collectively called the numeric +types.

+ +

Conversions

+ +

The following conversions are implicitly performed by the +expression language:

+ +

·         +From the the null literal to any reference type or nullable type.

+ +

·         +From an integer literal to an integral type or real type +provided the number is within the range of that type.

+ +

·         +From a real literal to a real +type provided the number is within the range of that type.

+ +

·         +From a string literal to an enum +type provided the string literal contains the name of a member of that enum type.

+ +

·         +From a source type that is assignment +compatible with the target type according to the Type.IsAssignableFrom method in .NET.

+ +

·         +From a non-nullable +value type to the nullable form of that value type.

+ +

·         +From a numeric type +to another numeric type with greater range.

+ +

The expression language permits explicit conversions using +the syntax type(expr), where type +is a type name optionally followed by ? and expr is an expression. +This syntax may be used to perform the following conversions:

+ +

·         +Between two types provided Type.IsAssignableFrom is true in one or both +directions.

+ +

·         +Between two types provided one or both are +interface types.

+ +

·         +Between the nullable +and non-nullable forms of any value type.

+ +

·         +Between any two types belonging to the set consisting of SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Decimal, Single, Double, Char, any enum type, as +well as the nullable forms of those types.

+ +

Operators

+ +

The table below shows the operators supported by the +expression language in order of precedence from highest to lowest. Operators in +the same category have equal precedence. In the table, x, y, and z denote expressions, T +denotes a type, and m +denotes a member.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Category

+
+

Expression

+
+

Description

+
+

Primary

+
+

x.m

+
+

Instance field or instance property + access. Any public field or property can be accessed.

+
+

x.m(…)

+
+

Instance method invocation. The method must be + public and must be declared in an accessible + type.

+
+

x[…]

+
+

Array or indexer access. + Multi-dimensional arrays are not supported.

+
+

T.m

+
+

Static field or static property + access. Any public field or property can be accessed.

+
+

T.m(…)

+
+

Static method invocation. The method must be + public and must be declared in an accessible + type.

+
+

T(…)

+
+

Explicit + conversion or constructor + invocation. Note that new is not required + in front of a constructor invocation.

+
+

new(…)

+
+

Data + object initializer. This construct can be used + to perform dynamic projections.

+
+

it

+
+

Current + instance. In contexts where members of a current object are implicitly in + scope, it is used to refer to the entire + object itself.

+
+

x(…)

+
+

Dynamic lambda invocation. Used to + reference another dynamic lambda expression.

+
+

iif(x, y, z)

+
+

Conditional expression. Alternate + syntax for x ? y : z.

+
+

Unary

+
+

-x

+
+

Negation. Supported types are Int32, Int64, Decimal, Single, + and Double.

+
+

!x

+

not x

+
+

Logical negation. Operand must be of type Boolean.

+
+

Multiplicative

+
+

x * y

+
+

Multiplication. Supported types are + Int32, UInt32, + Int64, UInt64, + Decimal, Single, + and Double.

+
+

x / y

+
+

Division. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, + and Double.

+
+

x % y

+

x mod y

+
+

Remainder. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, + and Double.

+
+

Additive

+
+

x + y

+
+

Addition or string concatenation. + Performs string concatenation if either operand is of type String. Otherwise, performs addition for the + supported types Int32, UInt32, Int64, UInt64, Decimal, Single, Double, DateTime, and TimeSpan.

+
+

x – y

+
+

Subtraction. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, Double, DateTime, and TimeSpan.

+
+

x & y

+
+

String concatenation. Operands may + be of any type.

+
+

Relational

+
+

x = y

+

x == y

+
+

Equal. Supported for reference + types and the primitive types. Assignment is + not supported.

+
+

x != y

+

x <> + y

+
+

Not equal. Supported for reference + types and the primitive types.

+
+

x < y

+
+

Less than. Supported for all primitive types except Boolean, Object and + Guid.

+
+

x > y

+
+

Greater than. Supported for all primitive types except Boolean, Object and + Guid.

+
+

x <= y

+
+

Less than or equal. Supported for + all primitive types except Boolean, Object and + Guid.

+
+

x >= y

+
+

Greater than or equal. Supported + for all primitive types except Boolean, Object and + Guid.

+
+

Logical AND

+
+

x + && y

+

x and y

+
+

Logical AND. Operands must be of type Boolean.

+
+

Logical OR

+
+

x || y

+

x or y

+
+

Logical OR. Operands must be of type Boolean.

+
+

Conditional

+
+

x ? y : z

+
+

Evaluates y + if x is true, evaluates z if x is false.

+
+ +

Method and Constructor +Invocations

+ +

The expression language limits invocation of methods and +constructors to those declared public in the accessible +types. This restriction exists to protect against unintended side effects +from invocation of arbitrary methods.

+ +

The expression language permits getting (but not setting) +the value of any reachable public field, property, or indexer.

+ +

Overload resolution for methods, constructors, and indexers +uses rules similar to C#. In informal terms, overload resolution will pick the +best matching method, constructor, or indexer, or report an ambiguity error if +no single best match can be identified.

+ +

Note that constructor invocations are not prefixed by new. The following example creates a DateTime instance for a specfic year, month, and day using a constructor +invocation:

+ +

orders.Where("OrderDate +>= DateTime(2007, 1, 1)");

+ +

Data +Object Initializers

+ +

A data object initializer creates +a data class and returns an instance of +that class. The properties of the data class are inferred from the data object initializer. Specifically, a data object initializer of the form

+ +

new(e1 as p1, e2 as p2, e3 as p3)

+ +

creates a data class with three +properties, p1, p2, +and p3, the types of which are inferred from +the expressions e1, e2, +and e3, and returns an instance of that data +class with the properties initialized to the values computed by e1, e2, and e3. A property initializer +may omit the as keyword and the property name +provided the associated expression is a field or property access. The example

+ +

customers.Select("new(CompanyName +as Name, Phone)");

+ +

creates a data class with two +properties, Name and Phone, +and returns a sequence of instances of that data class initialized from the CompanyName and Phone properties of each customer.

+ +

Current +Instance

+ +

When parsing a lambda expression with a single unnamed +parameter, the members of the unnamed parameter are automatically in scope in +the expression string, and the current instance given by the unnamed +parameter can be referenced in whole using the keyword it. For example,

+ +

customers.Where("Country = @0", +country);

+ +

is equivalent to

+ +

customers.Where("it.Country += @0", country);

+ +

The IQueryable +extension methods all parse their expression arguments as lambda +expressions with a single unnamed parameter.

+ +

Dynamic Lambda Invocation

+ +

An expression can reference other dynamic lambda expressions +through dynamic lambda +invocations. A dynamic lambda invocation consists of a substitution +variable identifier that references an instance of System.Linq.Expressions.LambdaExpression, +followed by an argument list. The arguments supplied must be compatible with +the parameter list of the given dynamic lambda expression.

+ +

The following parses two separate dynamic lambda expressions +and then combines them in a predicate expression through dynamic lambda +invocations:

+ +

Expression<Func<Customer, bool>> e1 =
+    DynamicExpression.ParseLambda<Customer, bool>("City = \"London\"");
+Expression<Func<Customer, +bool>> e2 =
+    DynamicExpression.ParseLambda<Customer, bool>("Orders.Count >= 10");
+IQueryable<Customer> +query =
+    db.Customers.Where("@0(it) and @1(it)", e1, e2);

+ +

It is of course possible to combine static and dynamic +lambda expressions in this fashion:

+ +

Expression<Func<Customer, bool>> e1 =
+    c => c.City == "London";
+Expression<Func<Customer, +bool>> e2 =
+    DynamicExpression.ParseLambda<Customer, bool>("Orders.Count >= 10");
+IQueryable<Customer> +query =
+    db.Customers.Where("@0(it) and @1(it)", e1, e2);

+ +

The examples above both have the same effect as:

+ +

IQueryable<Customer> query =
+    db.Customers.Where(c => c.City == "London" +&& c.Orders.Count >= 10);n a predicate expression c lambda expressions and then combines +them through dynamic lambda invocations

+ +

combines two seperately +parsed lambda expressions in a single predicate:e +dynamic lambda expression. System.Linq.Expressions.LamSequence operators

+ +

A subset of the Standard Query Operators is supported for +objects that implement IEnumerable<T>. Specifically, the following constructs are +permitted, where seq is an IEnumerable<T> +instance, predicate is a boolean +expression, and selector is an expression of any type:

+ +

seq . Where +( predicate )                            +seq +. Any ( )

+ +

seq . Any +( predicate )                                 +seq +. All ( predicate )

+ +

seq . Count +( )                                                +seq . Count +( predicate )

+ +

seq . Min +( selector )                                    +seq +. Max ( selector )

+ +

seq . Sum +( selector )                                    +seq +. Average ( selector )

+ +

In the predicate and selector expressions, the +members of the current instance for that +sequence operator are automatically in scope, and the instance itself can be +referenced using the keyword it. An example:

+ +

customers.Where("Orders.Any(Total +>= 1000)");

+ +

Enum type support

+ +

The expression language supports an implicit +conversion from a string literal to an enum type +provided the string literal contains the name of a member of that enum type. For example,

+ +

orders.Where("OrderDate.DayOfWeek += \"Monday\"");

+ +

is equivalent to

+ +

orders.Where("OrderDate.DayOfWeek += @0", DayOfWeek.Monday);

+ +

 

+ +
+ + + + diff --git a/NzbDrone.Web/Helpers/DataTablesModelBinder.cs b/NzbDrone.Web/Helpers/DataTablesModelBinder.cs new file mode 100644 index 000000000..77b79f620 --- /dev/null +++ b/NzbDrone.Web/Helpers/DataTablesModelBinder.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using NzbDrone.Web.Models; + +namespace NzbDrone.Web.Helpers +{ + /// + /// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html + /// + public class DataTablesModelBinder : IModelBinder + { + public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) + { + DataTablesParams obj = new DataTablesParams(); + var request = controllerContext.HttpContext.Request.Params; + + obj.iDisplayStart = Convert.ToInt32(request["iDisplayStart"]); + obj.iDisplayLength = Convert.ToInt32(request["iDisplayLength"]); + obj.iColumns = Convert.ToInt32(request["iColumns"]); + obj.sSearch = request["sSearch"]; + obj.bEscapeRegex = Convert.ToBoolean(request["bEscapeRegex"]); + obj.iSortingCols = Convert.ToInt32(request["iSortingCols"]); + obj.sEcho = int.Parse(request["sEcho"]); + + for (int i = 0; i < obj.iColumns; i++) + { + obj.bSortable.Add(Convert.ToBoolean(request["bSortable_" + i])); + obj.bSearchable.Add(Convert.ToBoolean(request["bSearchable_" + i])); + obj.sSearchColumns.Add(request["sSearch_" + i]); + obj.bEscapeRegexColumns.Add(Convert.ToBoolean(request["bEscapeRegex_" + i])); + obj.iSortCol.Add(Convert.ToInt32(request["iSortCol_" + i])); + obj.sSortDir.Add(request["sSortDir_" + i]); + } + return obj; + } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Models/DataTablesParams.cs b/NzbDrone.Web/Models/DataTablesParams.cs new file mode 100644 index 000000000..021ff7924 --- /dev/null +++ b/NzbDrone.Web/Models/DataTablesParams.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace NzbDrone.Web.Models +{ + public class DataTablesParams + { + public int iDisplayStart { get; set; } + public int iDisplayLength { get; set; } + public int iColumns { get; set; } + public string sSearch { get; set; } + public bool bEscapeRegex { get; set; } + public int iSortingCols { get; set; } + public int sEcho { get; set; } + public List bSortable { get; set; } + public List bSearchable { get; set; } + public List sSearchColumns { get; set; } + public List iSortCol { get; set; } + public List sSortDir { get; set; } + public List bEscapeRegexColumns { get; set; } + + public DataTablesParams() + { + bSortable = new List(); + bSearchable = new List(); + sSearchColumns = new List(); + iSortCol = new List(); + sSortDir = new List(); + bEscapeRegexColumns = new List(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Models/LogModel.cs b/NzbDrone.Web/Models/LogModel.cs new file mode 100644 index 000000000..a265dacf6 --- /dev/null +++ b/NzbDrone.Web/Models/LogModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace NzbDrone.Web.Models +{ + public class LogModel + { + public string Message { get; set; } + public string Time { get; set; } + public string Source { get; set; } + public string Method { get; set; } + public string Exception { get; set; } + public string ExceptionType { get; set; } + public string Level { get; set; } + public string Details { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index b1fb325d2..384ddf12e 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -45,6 +45,9 @@ x86 + + ..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll + ..\packages\EntityFramework.4.2.0.0\lib\net40\EntityFramework.dll @@ -270,6 +273,7 @@ + @@ -290,6 +294,7 @@ Global.asax + @@ -297,6 +302,8 @@ + + @@ -410,6 +417,7 @@ + @@ -680,6 +688,7 @@ + diff --git a/NzbDrone.Web/Views/History/Index.cshtml b/NzbDrone.Web/Views/History/Index.cshtml index dcfbfebfa..b9b8d7fef 100644 --- a/NzbDrone.Web/Views/History/Index.cshtml +++ b/NzbDrone.Web/Views/History/Index.cshtml @@ -15,7 +15,7 @@ }
- +
@@ -33,10 +33,6 @@ - @*@foreach(var history in Model) - { - Html.RenderPartial("History", history); - }*@
@@ -53,7 +49,7 @@ $(document).ready(function () { $('#historyGrid').removeClass('hidden-grid'); - oTable = $('#historyGrid').dataTable({ + oTable = $('.dataTablesGrid').dataTable({ //"sAjaxSource": "History/AjaxBinding", //"bProcessing": true, "bShowAll": false, diff --git a/NzbDrone.Web/Views/Log/Index.cshtml b/NzbDrone.Web/Views/Log/Index.cshtml index 08bf44234..60683569d 100644 --- a/NzbDrone.Web/Views/Log/Index.cshtml +++ b/NzbDrone.Web/Views/Log/Index.cshtml @@ -2,26 +2,6 @@ @using NzbDrone.Core.Instrumentation @using NzbDrone.Web.Helpers @model IEnumerable -@section Scripts{ - -} @{ ViewBag.Title = "Logs";} @section ActionMenu{ } + +@section HeaderContent{ + +} +
Log entries older than 30 days are automatically deleted.
-@{Html.Telerik().Grid().Name("logsGrid") - .TableHtmlAttributes(new { @class = "Grid" }) - .Columns(columns => - { - columns.Bound(c => c.Time).Title("Time").Width(170); - columns.Bound(c => c.Level).Title("Level").Width(70); - columns.Bound(c => c.Logger).Title("Source"); - columns.Bound(c => c.Message); - }) - .DetailView(detailView => detailView.ClientTemplate( - "
Method: <#= Method #>
" + - "
<#= ExceptionType #>
" + - "
<#= Exception #>
" - )) - .DataBinding(data => data.Ajax().Select("AjaxBinding", "Log").Enabled(true)) - .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.Time).Descending()).Enabled(true)) - .Pageable(paging => paging.Style(GridPagerStyles.Status).PageOnScroll(true).PageSize(100)) - .Filterable() - .ClientEvents(c => c.OnRowDataBound("onRowDataBound")) - .Scrollable(c => c.Height(500)) - .ClientEvents(clientEvents => - { - if (EnviromentProvider.IsProduction) - clientEvents.OnError("grid_onError"); - }) - .Render();} - + +
+ + + + + + + + @*Details Column*@ + + + + + +
TimeLevelSourceMessageDetails
+
+ +@section Scripts{ + +} \ No newline at end of file diff --git a/NzbDrone.Web/Views/Log/IndexOld.cshtml b/NzbDrone.Web/Views/Log/IndexOld.cshtml new file mode 100644 index 000000000..9763ee6ed --- /dev/null +++ b/NzbDrone.Web/Views/Log/IndexOld.cshtml @@ -0,0 +1,65 @@ +@using NzbDrone.Common +@using NzbDrone.Core.Instrumentation +@using NzbDrone.Web.Helpers +@model IEnumerable +@section Scripts{ + +} +@{ ViewBag.Title = "Logs";} +@section ActionMenu{ + +} +
+ Log entries older than 30 days are automatically deleted.
+@{Html.Telerik().Grid().Name("logsGrid") + .TableHtmlAttributes(new { @class = "Grid" }) + .Columns(columns => + { + columns.Bound(c => c.Time).Title("Time").Width(170); + columns.Bound(c => c.Level).Title("Level").Width(70); + columns.Bound(c => c.Logger).Title("Source"); + columns.Bound(c => c.Message); + }) + .DetailView(detailView => detailView.ClientTemplate( + "
Method: <#= Method #>
" + + "
<#= ExceptionType #>
" + + "
<#= Exception #>
" + )) + .DataBinding(data => data.Ajax().Select("AjaxBindingOld", "Log").Enabled(true)) + .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.Time).Descending()).Enabled(true)) + .Pageable(paging => paging.Style(GridPagerStyles.Status).PageOnScroll(true).PageSize(100)) + .Filterable() + .ClientEvents(c => c.OnRowDataBound("onRowDataBound")) + .Scrollable(c => c.Height(500)) + .ClientEvents(clientEvents => + { + if (EnviromentProvider.IsProduction) + clientEvents.OnError("grid_onError"); + }) + .Render();} + diff --git a/NzbDrone.Web/Views/Missing/Index.cshtml b/NzbDrone.Web/Views/Missing/Index.cshtml index 6c1ec22c8..cb5baa76d 100644 --- a/NzbDrone.Web/Views/Missing/Index.cshtml +++ b/NzbDrone.Web/Views/Missing/Index.cshtml @@ -16,7 +16,7 @@ }
- +
@@ -44,7 +44,7 @@ $(document).ready(function () { $('#historyGrid').removeClass('hidden-grid'); - oTable = $('#historyGrid').dataTable({ + oTable = $('.dataTablesGrid').dataTable({ //"sAjaxSource": "History/AjaxBinding", //"bProcessing": true, "bShowAll": false, diff --git a/NzbDrone.Web/packages.config b/NzbDrone.Web/packages.config index fe58107d3..8a9720d53 100644 --- a/NzbDrone.Web/packages.config +++ b/NzbDrone.Web/packages.config @@ -1,5 +1,6 @@  + diff --git a/packages/DynamicQuery.1.0/DynamicQuery.1.0.nupkg b/packages/DynamicQuery.1.0/DynamicQuery.1.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..1ece3c49fdec8d97599d1218f14284dcff01dafa GIT binary patch literal 46343 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ÿuq&SbMmSIu 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 literal 0 HcmV?d00001 diff --git a/packages/DynamicQuery.1.0/content/Dynamic Expressions.html b/packages/DynamicQuery.1.0/content/Dynamic Expressions.html new file mode 100644 index 000000000..3735c922d --- /dev/null +++ b/packages/DynamicQuery.1.0/content/Dynamic Expressions.html @@ -0,0 +1,2279 @@ + + + + + + + + +Dynamic Expression API + + + + + + + + + +
+ +

Dynamic Expressions +and Queries in LINQ

+ +

Database applications frequently rely on “Dynamic +SQL”—queries that are constructed at run-time through program logic. The LINQ +infrastructure supports similar capabilities through dynamic construction of +expression trees using the classes in the System.Linq.Expressions namespace. Expression +trees are an appropriate abstraction for a variety of scenarios, but for others +a string-based representation may be more convenient. The Dynamic Expression API extends the core +LINQ API with that capability. The API is located in the Dynamic.cs +source file and provides

+ +

·         +Dynamic parsing of strings to produce +expression trees (the ParseLambda +and Parse methods),

+ +

·         +Dynamic creation of “Data Classes” (the CreateClass methods), +and

+ +

·         +Dynamic string-based querying through LINQ +providers (the IQueryable extension +methods).

+ +

The Dynamic Expression API relies on a simple expression language for formulating +expressions and queries in strings.

+ +

Dynamic Expression API

+ +

The Dynamic +Expression API is brought into scope by using (importing) the System.Linq.Dynamic +namespace. Below is an example of applying the Dynamic Expression API to a LINQ +to SQL data source.

+ +

var +query =
+    db.Customers.
+    Where("City += @0 and Orders.Count >= @1", "London", 10).
+    OrderBy("CompanyName").
+    Select("new(CompanyName as Name, Phone)");

+ +

Note that expressions in the query are strings that could +have been dynamically constructed at run-time.

+ +

The ParseLambda Methods

+ +

The System.Linq.Dynamic.DynamicExpression +class defines the following overloaded ParseLambda methods for dynamically parsing +and creating lambda expressions.

+ +

public static LambdaExpression ParseLambda(
+    ParameterExpression[] +parameters, Type resultType,
+    string expression, params object[] values);

+ +

public static LambdaExpression ParseLambda(
+    Type argumentType, +Type resultType,
+    string expression, params object[] values);

+ +

public static Expression<Func<TArgument, +TResult>>
+    ParseLambda<TArgument, +TResult>(
+        string +expression, params object[] values);

+ +

The first ParseLambda overload parses a lambda +expression with the given parameters and expression body and returns an Expression<Func<…>> +instance representing the result. If the resultType parameter is non-null it specifies +the required result type for the expression. The values +parameter supplies zero or more substitution +values that may be referenced in the expression.

+ +

The example

+ +

ParameterExpression +x = Expression.Parameter(typeof(int), "x");
+ParameterExpression +y = Expression.Parameter(typeof(int), "y");
+LambdaExpression e += DynamicExpression.ParseLambda(
+    new ParameterExpression[] { x, y }, null, "(x + y) * +2");

+ +

creates and assigns an Expression<Func<int, int, int>> +instance to e representing the expression (x + y) * 2. If a required result type is specified, as in

+ +

LambdaExpression +e = DynamicExpression.ParseLambda(
+    new ParameterExpression[] { x, y }, typeof(double), "(x + y) * +2");

+ +

the parsing operation will include +an implicit conversion to the given result type, in +this case yielding an Expression<Func<int, int, +double>> instance.

+ +

The second ParseLambda overload parses a lambda +expression with a single unnamed parameter of a specified argumentType. This method corresponds to +calling the first ParseLambda overload with a parameters argument containing a single ParameterExpression with an +empty or null Name property.

+ +

­When parsing a lambda expression with a single unnamed +parameter, the members of the unnamed parameter are automatically in scope in +the expression string, and the current instance +given by the unnamed parameter can be referenced in whole using the keyword it. The example

+ +

LambdaExpression +e = DynamicExpression.ParseLambda(
+    typeof(Customer), typeof(bool),
+    "City = @0 and Orders.Count >= @1",
+    "London", 10);

+ +

creates and assigns an Expression<Func<Customer, bool>> instance to e. +Note that City and Orders +are members of Customer that are automatically +in scope. Also note the use of substitution +values to supply the constant values "London" +and 10.

+ +

The third ParseLambda overload is a genericly +typed version of the second overload. The example below produces the same Expression<Func<Customer, bool>> instance as the example above, but is +statically typed to that exact type.

+ +

Expression<Func<Customer, bool>> e =
+    DynamicExpression.ParseLambda<Customer, bool>(
+        "City += @0 and Orders.Count >= @1",
+        "London", +10);

+ +

The +Parse Method

+ +

The System.Linq.Dynamic.DynamicExpression +class defines the following method for parsing and creating expression tree +fragments.

+ +

public static Expression +Parse(Type resultType, +string expression,
+    params +object[] values);

+ +

The Parse method parses the given expression +and returns an expression tree. If the resultType parameter is non-null it specifies +the required result type of the expression. The values +parameter supplies zero or more substitution +values that may be referenced in the expression.

+ +

Unlike the ParseLambda +methods, the Parse method returns an “unbound” +expression tree fragment. The following example uses Parse to produce the same result as a previous example:

+ +

ParameterExpression +x = Expression.Parameter(typeof(int), "x");
+ParameterExpression +y = Expression.Parameter(typeof(int), "y");
+Dictionary<string, +object> symbols = new +Dictionary<string, +object>();
+symbols.Add("x", +x);
+symbols.Add("y", +y);
+Expression body = DynamicExpression.Parse(null, "(x + y) * +2", symbols);
+LambdaExpression e += Expression.Lambda(
+    body, new ParameterExpression[] { +x, y });

+ +

Note the use of a Dictionary<string, +object> to provide a dictionary of named substitution values that can be referenced in +the expression.

+ +

Substitution Values

+ +

Several methods in the Dynamic Expression API permit substitution values to +be specified through a parameter array. Substitution values are referenced in +an expression using identifiers of the form @x, where x is an +index into the parameter array. The last element of the parameter array may be +an object that implements IDictionary<string, object>. If so, this dictionary is +used to map identifiers to substitution values during parsing.

+ +

An identifier that references a substitution value is +processed as follows:

+ +

·         +If the value is of type System.Linq.Expressions.LambdaExpression, the +identifier must occur as part of a dynamic +lambda invocation. This allows composition of dynamic lambda expressions.

+ +

·         +Otherwise, if the value is of type System.Linq.Expressions.Expression, the given +expression is substituted for the identifier.

+ +

·         +Otherwise, the Expression.Constant method is used to create a constant expression from +the value which is then substituted for the identifier.

+ +

Dynamic Data Classes

+ +

A data class is a class that contains only data members. The +System.Linq.Dynamic.DynamicExpression +class defines the following methods for dynamically creating data classes.

+ +

public static Type CreateClass(params +DynamicProperty[] +properties);

+ +

public static Type CreateClass(IEnumerable<DynamicProperty> +properties);

+ +

The CreateClass +method creates a new data class with a given set of public properties and +returns the System.Type +object for the newly created class. If a data class with an identical sequence +of properties has already been created, the System.Type object for this class is returned.

+ +

Data classes implement private instance variables and +read/write property accessors for the specified +properties. Data classes also override the Equals +and GetHashCode +members to implement by-value equality.

+ +

Data classes are created in an in-memory assembly in the +current application domain. All data classes inherit from System.Linq.Dynamic.DynamicClass and are given +automatically generated names that should be considered private (the names will +be unique within the application domain but not across multiple invocations of +the application). Note that once created, a data class stays in memory for the +lifetime of the current application domain. There is currently no way to unload +a dynamically created data class.

+ +

The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers. This +feature in turn is often used with the dynamic Select +method to create projections.

+ +

The example below uses CreateClass to create a data class with two +properties, Name and Birthday, +and then uses .NET reflection to create an instance of the class and assign +values to the properties.

+ +

DynamicProperty[] +props = new DynamicProperty[] {
+    new DynamicProperty("Name", +typeof(string)),
+    new DynamicProperty("Birthday", +typeof(DateTime)) };
+Type type = DynamicExpression.CreateClass(props);
+object obj = Activator.CreateInstance(type);
+t.GetProperty("Name").SetValue(obj, "Albert", null);
+t.GetProperty("Birthday").SetValue(obj, new DateTime(1879, +3, 14), null);
+Console.WriteLine(obj);

+ +

IQueryable Extension Methods

+ +

The System.Linq.Dynamic.DynamicQueryable +class implements the following extension methods for dynamically querying +objects that implement the IQueryable<T> +interface.

+ +

public static IQueryable +Where(this IQueryable +source,
+    string predicate, params object[] values);

+ +

public static IQueryable<T> +Where<T>(this IQueryable<T> +source,
+    string predicate, params object[] values);

+ +

public static IQueryable +Select(this IQueryable +source,
+    string selector, params object[] values);

+ +

public static IQueryable OrderBy(this IQueryable source,
+    string ordering, params object[] values);

+ +

public static IQueryable<T> +OrderBy<T>(this +IQueryable<T> source,
+    string ordering, params object[] values);

+ +

public static IQueryable +Take(this IQueryable +source, int count);

+ +

public static IQueryable +Skip(this IQueryable +source, int count);

+ +

public static IQueryable GroupBy(this IQueryable source,
+    string keySelector, +string elementSelector, +params object[] values);

+ +

public static bool +Any(this IQueryable +source);

+ +

public static int +Count(this IQueryable +source);

+ +

These methods correspond to their System.Linq.Queryable counterparts, except +that they operate on IQueryable instead of IQueryable<T> and use strings instead of lambda +expressions to express predicates, selectors, and orderings. IQueryable is the non-generic base interface for IQueryable<T>, so the methods can be used even +when T isn’t known on beforehand, i.e. when the +source of a query is dynamically determined. (Note that because a dynamic +predicate or ordering does not affect the result type, generic overloads are +provided for Where and OrderBy in order to preserve strong typing +when possible.)

+ +

The predicate, selector, ordering, keySelector, and elementSelector parameters +are strings containing expressions written in the expression language. In the expression +strings, the members of the current instance +are automatically in scope and the instance itself can be referenced using the +keyword it.

+ +

The OrderBy +method permits a sequence of orderings to be specified, separated by commas. +Each ordering may optionally be followed by asc or ascending +to indicate ascending order, or desc or descending +to indicate descending order. The default order is ascending. The example

+ +

products.OrderBy("Category.CategoryName, +UnitPrice descending");

+ +

orders a sequence of products by +ascending category name and, within each category, descending unit price.

+ +

The ParseException Class

+ +

The Dynamic Expression API reports parsing errors using the System.Linq.Dynamic.ParseException +class. The Position property of the ParseException class gives +the character index in the expression string at which the parsing error +occurred.

+ +

Expression Language

+ +

The expression language implemented by the Dynamic +Expression API provides a simple and convenient way of writing expressions that +can be parsed into LINQ expression trees. The language supports most of the +constructs of expression trees, but it is by no means a complete query or +programming language. In particular, the expression language does not support +statements or declarations.

+ +

The expression language is designed to be familiar to C#, +VB, and SQL users. For this reason, some operators are present in multiple +forms, such as && and and.

+ +

Identifiers

+ +

An Identifier consists of a letter or underscore followed by +any number of letters, digits, or underscores. In order to reference an +identifier with the same spelling as a keyword, the identifier must be prefixed +with a single @ character. Some examples of identifiers:

+ +

x   Hello   +m_1   @true   @String

+ +

Identifiers of the from @x, where x is an integral number +greater than or equal to zero, are used to denote the substitution values, if any, that were passed +to the expression parser. For example:

+ +

customers.Where("Country = @0", +country);

+ +

Casing is not significant in identifiers or keywords.

+ +

Literals

+ +

The expression language supports integer, real, string, and +character literals.

+ +

An integer +literal consists of a sequence of digits. The type of an integer +literal is the first of the types Int32, UInt32, Int64, or UInt64 that can represent the given value. An integer +literal implicitly converts to any other numeric type +provided the number is in the range of that type. Some examples of integer +literals:

+ +

0   123   10000

+ +

A real +literal consists of an integral part followed by a fractional part +and/or an exponent. The integral part is a sequence of one or more digits. The +fractional part is a decimal point followed by one or more digits. The exponent +is the letter e or E +followed by an optional + or sign followed by one or more digits. The type of a +real literal is Double. +A real literal implicitly converts to any other real type +provided the number is in the range of that type. Some examples of real +literals:

+ +

1.0   2.25   10000.0   +1e0   1e10   1.2345E-4

+ +

A string +literal consists of zero or more characters enclosed in double +quotes. Inside a string literal, a double quote is written as two consecutive +double quotes. The type of a string literal is String. +Some examples of string literals:

+ +

"hello"   +""    +"""quoted"""   "'"

+ +

A character +literal consists of a single character enclosed in single quotes. +Inside a character literal, a single quote is written as two consecutive single +quotes. The type of a character literal is Char. +Some examples of character literals:

+ +

'A'   '1'   ''''   '"'

+ +

Constants

+ +

The predefined constants true +and false denote the two values of the type Boolean.

+ +

The predefined constant null +denotes a null reference. The null constant is +of type Object, but is also implicitly +convertible to any reference type.

+ +

Types

+ +

The expression language defines the following primitive types:

+ +

Object                +Boolean             +Char                     +String                +SByte                   +Byte
+Int16                   +UInt16                +Int32                   +UInt32                +Int64                   +UInt64
+Decimal     Single                +Double                +DateTime           +TimeSpan           +Guid

+ +

The primitive types correspond to the similarly named types +in the System namespace of the .NET Framework Base Class Library. The +expression language also defines a set of accessible +types consisting of the primitive types and the following types +from the System namespace:

+ +

Math                     +Convert

+ +

The accessible types are the only types that can be +explicitly referenced in expressions, and method invocations in the expression +language are restricted to methods declared in the accessible types.

+ +

The nullable form of a value type is +referenced by writing a ? +after the type name. For example, Int32? denotes the nullable form of Int32.

+ +

The non-nullable +and nullable forms of the types SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, and UInt64 are +collectively called the integral +types.

+ +

The non-nullable and nullable forms of +the types Single, Double, +and Decimal are collectively called the real types.

+ +

The integral types and real types +are collectively called the numeric +types.

+ +

Conversions

+ +

The following conversions are implicitly performed by the +expression language:

+ +

·         +From the the null literal to any reference type or nullable type.

+ +

·         +From an integer literal to an integral type or real type +provided the number is within the range of that type.

+ +

·         +From a real literal to a real +type provided the number is within the range of that type.

+ +

·         +From a string literal to an enum +type provided the string literal contains the name of a member of that enum type.

+ +

·         +From a source type that is assignment +compatible with the target type according to the Type.IsAssignableFrom method in .NET.

+ +

·         +From a non-nullable +value type to the nullable form of that value type.

+ +

·         +From a numeric type +to another numeric type with greater range.

+ +

The expression language permits explicit conversions using +the syntax type(expr), where type +is a type name optionally followed by ? and expr is an expression. +This syntax may be used to perform the following conversions:

+ +

·         +Between two types provided Type.IsAssignableFrom is true in one or both +directions.

+ +

·         +Between two types provided one or both are +interface types.

+ +

·         +Between the nullable +and non-nullable forms of any value type.

+ +

·         +Between any two types belonging to the set consisting of SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Decimal, Single, Double, Char, any enum type, as +well as the nullable forms of those types.

+ +

Operators

+ +

The table below shows the operators supported by the +expression language in order of precedence from highest to lowest. Operators in +the same category have equal precedence. In the table, x, y, and z denote expressions, T +denotes a type, and m +denotes a member.

+ +
Series Title
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Category

+
+

Expression

+
+

Description

+
+

Primary

+
+

x.m

+
+

Instance field or instance property + access. Any public field or property can be accessed.

+
+

x.m(…)

+
+

Instance method invocation. The method must be + public and must be declared in an accessible + type.

+
+

x[…]

+
+

Array or indexer access. + Multi-dimensional arrays are not supported.

+
+

T.m

+
+

Static field or static property + access. Any public field or property can be accessed.

+
+

T.m(…)

+
+

Static method invocation. The method must be + public and must be declared in an accessible + type.

+
+

T(…)

+
+

Explicit + conversion or constructor + invocation. Note that new is not required + in front of a constructor invocation.

+
+

new(…)

+
+

Data + object initializer. This construct can be used + to perform dynamic projections.

+
+

it

+
+

Current + instance. In contexts where members of a current object are implicitly in + scope, it is used to refer to the entire + object itself.

+
+

x(…)

+
+

Dynamic lambda invocation. Used to + reference another dynamic lambda expression.

+
+

iif(x, y, z)

+
+

Conditional expression. Alternate + syntax for x ? y : z.

+
+

Unary

+
+

-x

+
+

Negation. Supported types are Int32, Int64, Decimal, Single, + and Double.

+
+

!x

+

not x

+
+

Logical negation. Operand must be of type Boolean.

+
+

Multiplicative

+
+

x * y

+
+

Multiplication. Supported types are + Int32, UInt32, + Int64, UInt64, + Decimal, Single, + and Double.

+
+

x / y

+
+

Division. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, + and Double.

+
+

x % y

+

x mod y

+
+

Remainder. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, + and Double.

+
+

Additive

+
+

x + y

+
+

Addition or string concatenation. + Performs string concatenation if either operand is of type String. Otherwise, performs addition for the + supported types Int32, UInt32, Int64, UInt64, Decimal, Single, Double, DateTime, and TimeSpan.

+
+

x – y

+
+

Subtraction. Supported types are Int32, UInt32, Int64, UInt64, Decimal, Single, Double, DateTime, and TimeSpan.

+
+

x & y

+
+

String concatenation. Operands may + be of any type.

+
+

Relational

+
+

x = y

+

x == y

+
+

Equal. Supported for reference + types and the primitive types. Assignment is + not supported.

+
+

x != y

+

x <> + y

+
+

Not equal. Supported for reference + types and the primitive types.

+
+

x < y

+
+

Less than. Supported for all primitive types except Boolean, Object and + Guid.

+
+

x > y

+
+

Greater than. Supported for all primitive types except Boolean, Object and + Guid.

+
+

x <= y

+
+

Less than or equal. Supported for + all primitive types except Boolean, Object and + Guid.

+
+

x >= y

+
+

Greater than or equal. Supported + for all primitive types except Boolean, Object and + Guid.

+
+

Logical AND

+
+

x + && y

+

x and y

+
+

Logical AND. Operands must be of type Boolean.

+
+

Logical OR

+
+

x || y

+

x or y

+
+

Logical OR. Operands must be of type Boolean.

+
+

Conditional

+
+

x ? y : z

+
+

Evaluates y + if x is true, evaluates z if x is false.

+
+ +

Method and Constructor +Invocations

+ +

The expression language limits invocation of methods and +constructors to those declared public in the accessible +types. This restriction exists to protect against unintended side effects +from invocation of arbitrary methods.

+ +

The expression language permits getting (but not setting) +the value of any reachable public field, property, or indexer.

+ +

Overload resolution for methods, constructors, and indexers +uses rules similar to C#. In informal terms, overload resolution will pick the +best matching method, constructor, or indexer, or report an ambiguity error if +no single best match can be identified.

+ +

Note that constructor invocations are not prefixed by new. The following example creates a DateTime instance for a specfic year, month, and day using a constructor +invocation:

+ +

orders.Where("OrderDate +>= DateTime(2007, 1, 1)");

+ +

Data +Object Initializers

+ +

A data object initializer creates +a data class and returns an instance of +that class. The properties of the data class are inferred from the data object initializer. Specifically, a data object initializer of the form

+ +

new(e1 as p1, e2 as p2, e3 as p3)

+ +

creates a data class with three +properties, p1, p2, +and p3, the types of which are inferred from +the expressions e1, e2, +and e3, and returns an instance of that data +class with the properties initialized to the values computed by e1, e2, and e3. A property initializer +may omit the as keyword and the property name +provided the associated expression is a field or property access. The example

+ +

customers.Select("new(CompanyName +as Name, Phone)");

+ +

creates a data class with two +properties, Name and Phone, +and returns a sequence of instances of that data class initialized from the CompanyName and Phone properties of each customer.

+ +

Current +Instance

+ +

When parsing a lambda expression with a single unnamed +parameter, the members of the unnamed parameter are automatically in scope in +the expression string, and the current instance given by the unnamed +parameter can be referenced in whole using the keyword it. For example,

+ +

customers.Where("Country = @0", +country);

+ +

is equivalent to

+ +

customers.Where("it.Country += @0", country);

+ +

The IQueryable +extension methods all parse their expression arguments as lambda +expressions with a single unnamed parameter.

+ +

Dynamic Lambda Invocation

+ +

An expression can reference other dynamic lambda expressions +through dynamic lambda +invocations. A dynamic lambda invocation consists of a substitution +variable identifier that references an instance of System.Linq.Expressions.LambdaExpression, +followed by an argument list. The arguments supplied must be compatible with +the parameter list of the given dynamic lambda expression.

+ +

The following parses two separate dynamic lambda expressions +and then combines them in a predicate expression through dynamic lambda +invocations:

+ +

Expression<Func<Customer, bool>> e1 =
+    DynamicExpression.ParseLambda<Customer, bool>("City = \"London\"");
+Expression<Func<Customer, +bool>> e2 =
+    DynamicExpression.ParseLambda<Customer, bool>("Orders.Count >= 10");
+IQueryable<Customer> +query =
+    db.Customers.Where("@0(it) and @1(it)", e1, e2);

+ +

It is of course possible to combine static and dynamic +lambda expressions in this fashion:

+ +

Expression<Func<Customer, bool>> e1 =
+    c => c.City == "London";
+Expression<Func<Customer, +bool>> e2 =
+    DynamicExpression.ParseLambda<Customer, bool>("Orders.Count >= 10");
+IQueryable<Customer> +query =
+    db.Customers.Where("@0(it) and @1(it)", e1, e2);

+ +

The examples above both have the same effect as:

+ +

IQueryable<Customer> query =
+    db.Customers.Where(c => c.City == "London" +&& c.Orders.Count >= 10);n a predicate expression c lambda expressions and then combines +them through dynamic lambda invocations

+ +

combines two seperately +parsed lambda expressions in a single predicate:e +dynamic lambda expression. System.Linq.Expressions.LamSequence operators

+ +

A subset of the Standard Query Operators is supported for +objects that implement IEnumerable<T>. Specifically, the following constructs are +permitted, where seq is an IEnumerable<T> +instance, predicate is a boolean +expression, and selector is an expression of any type:

+ +

seq . Where +( predicate )                            +seq +. Any ( )

+ +

seq . Any +( predicate )                                 +seq +. All ( predicate )

+ +

seq . Count +( )                                                +seq . Count +( predicate )

+ +

seq . Min +( selector )                                    +seq +. Max ( selector )

+ +

seq . Sum +( selector )                                    +seq +. Average ( selector )

+ +

In the predicate and selector expressions, the +members of the current instance for that +sequence operator are automatically in scope, and the instance itself can be +referenced using the keyword it. An example:

+ +

customers.Where("Orders.Any(Total +>= 1000)");

+ +

Enum type support

+ +

The expression language supports an implicit +conversion from a string literal to an enum type +provided the string literal contains the name of a member of that enum type. For example,

+ +

orders.Where("OrderDate.DayOfWeek += \"Monday\"");

+ +

is equivalent to

+ +

orders.Where("OrderDate.DayOfWeek += @0", DayOfWeek.Monday);

+ +

 

+ +
+ + + + diff --git a/packages/DynamicQuery.1.0/lib/35/Dynamic.dll b/packages/DynamicQuery.1.0/lib/35/Dynamic.dll new file mode 100644 index 0000000000000000000000000000000000000000..cac74ed4eb751c586b5f3ad752a7b60b538ea33e GIT binary patch literal 46080 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 M;D6=*ztO<|0f%w+R{#J2 literal 0 HcmV?d00001