How to create a very dynamic LinqToEntity query?

I need to build a very dynamic Linq query on a different number of tables. For example, I have related tables:
TABLE_A
 - ID
 - Name
 - Desc

TABLE_B
 - ID
 - Table_A_ID
 - Name
 - Desc

Table_C
 - ID
 - Table_B_ID
 - Name
 - Desc

I have a dictionary with table dependency information containing:
  tableName, parentTableName, foreignKey, parentPK
Example:
  "Table_B", "Table_A", "Table_A_ID", "ID"
  "Table_C", "Table_B", "Table_B_ID", "ID "

-> tableInfo ["Table_B"]. ForeignKey will return "Table_A_ID", etc.

Now the user can choose which columns he wants to see.
Examples:

Table_B.Name, Table_C.Desc
  or Table_A.Name, Table_B.Name
  or Table_A.Name, Table_B.Name, Table_B.Desc, Table_C.Name

:
, 3:
viewInfo [ "_A" ] ""
viewInfo [ "Table_B" ] "" , "Desc"
viewInfo [ "Table_C" ] ""

, , ?

+3
3

, NLinq, Codeplex. , "" Linq!

prject:

NLinq - , Linq Visual Studio.Net 2003 Visual Studio 2005 (# VB.Net), Linq Linq To Objects. NLinq # 3.0 , .

:

Data sources used for the samples
        Person[] people = new Person[] { 
            new Person("Bill", 31), 
            new Person("John", 30), 
            new Person("Cindy", 25), 
            new Person("Sue", 29) 
        };

        // For testing physical links
        people[0].Friends.Add(people[0]);
        people[0].Friends.Add(people[1]);
        people[1].Friends.Add(people[2]);
        people[2].Friends.Add(people[3]);
        people[3].Friends.Add(people[0]);

        // For testing logical links
        Address[] addresses = new Address[] {
            new Address("Bill", "Redmon"),
            new Address("Bill", "Boston"),
            new Address("Cindy", "New York")
        };

Projections query = new NLinqQuery(
                @"  from c in people 
                    from d in people
                    where c.Age > d.Age
                    select new NLinq.Play.Person ( c.Firstname, d.Age )");

        linq = new LinqToMemory(query);
        linq.AddSource("people", people);


Result:
Sue (25)
John (25)
John (29)
Bill (30)
Bill (25)
Bill (29)
+1

, , , .

LINQ , System.Linq.Expressions. , .

LINQPad , , , , , .

, LINQPad .

var query = from p in Puzzles
select p;

query.Expression.Dump(20);

LINQPad Screenshot

, , LINQ?

, :

var query = from person in data
   select person;

" ".

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace TestLinqGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            // Set up dummy data
            var data = new[]
                           {
                               new {Name = "Fred"},
                               new {Name = "Simon"}
                           }.AsQueryable();
            var dataType = data.ElementType;

            // IQueryable: data
            var source = Expression.Constant(data);

            // Parameter: person
            var parameter = Expression.Parameter(dataType, "person");

            // person => person
            var lambda = Expression.Lambda(parameter, parameter);

            // Expression: data.Select(person => person)
            var callSelect = Expression.Call(GetSelect().MakeGenericMethod(dataType, dataType), source, Expression.Quote(lambda));

            // IQueryable: data.Select(person => person)
            var query = data.Provider.CreateQuery(callSelect);

            // Execute query
            var results = query.Cast<object>().ToList();

        }

        private static MethodInfo GetSelect()
        {
            // Get MethodInfo of the following method from System.Linq.Queryable:
            // public static IQueryable<TSource> Select<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
            return typeof(System.Linq.Queryable).GetMethods().Where(
                method => method.Name == "Select" && method.GetParameters().Length == 2 &&
                          method.GetParameters()[1].ParameterType.GetGenericArguments()[0].Name == typeof(Func<,>).Name).Single();
        }

    }
}

, . , , .

Queryable.Select Reflector , . :

public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, int, TResult>> selector)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (selector == null)
    {
        throw Error.ArgumentNull("selector");
    }
    return source.Provider.CreateQuery<TResult>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TResult) }), new Expression[] { source.Expression, Expression.Quote(selector) }));
}

, Queryable.Select LINQ . LINQ - - TSQL. Select .

- LINQ.

, , Queryable.Where LINQ. (select new {x, y, z} ..), . , . System.Reflection.Emit - .

, LINQ, LINQ to Entities, LINQ to SQL, Mindscape Lightspeed LINQ , AsQueryable.

, LINQ, IQueryable Mindscape Lightspeed IQueryables, . , IQueryable, AsQueryable, LINQ. - , , . , .

+4

Dynamic LINQ, . , .

, , LINQ. , - , , . , , , . , ( ) , , intellisense.

+3

Source: https://habr.com/ru/post/1760101/


All Articles