I need to create a dynamic linq expression for a dynamic search.The basic search is working but it fails to work with collection. I am able to get the book's title and author but fails to get the required page heading. I get the exception in line "left11 = Expression.Property(page1, "Heading");". I think the expression that i built is unable to recognise the List. How could this be possible? Please see the below code and stacktrace exception.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace XMLStorageAndFilter
{
public class Books
{
public Books()
{
Page = new List<Page>();
}
public string Title { get; set; }
public Author Author { get; set; }
public List<Page> Page { get; set; }
}
public class Author
{
public string FirstName { get; set; }
}
public class Page
{
public string Heading { get; set; }
}
public class Program2
{
static void Main()
{
Page page = new Page();
page.Heading = "Heading";
Books bok = new Books();
bok.Title = "Title";
bok.Author = new Author() { FirstName = "FirstName" };
bok.Page.Add(page);
List<Books> testList = new List<Books>();
testList.Add(bok);
IQueryable<Books> queryableTestData = testList.AsQueryable<Books>();
ParameterExpression pe11 = Expression.Parameter(typeof(Books), "p");
Expression left11 = Expression.Property(pe11, "Title");
Expression right11 = Expression.Constant("Title");
Expression e11 = Expression.Equal(left11, right11);
var author = Expression.Property(pe11, "Author");
left11 = Expression.Property(author, "FirstName");
right11 = Expression.Constant("FirstName");
Expression e21 = Expression.Equal(left11, right11);
Expression predicateBody11 = Expression.And(e11, e21);
Expression<Func<Books, bool>> condition = Expression.Lambda
<Func<Books, bool>>(predicateBody11, new ParameterExpression[] { pe11 });
var q = queryableTestData.Where(condition);
var page1 = Expression.Property(pe11, "Page");
left11 = Expression.Property(page1, "Heading");
right11 = Expression.Constant("Heading");
Expression e22 = Expression.Equal(left11, right11);
Expression predicateBody12 = Expression.And(e11, e22);
Expression<Func<Books, bool>> condition2 = Expression.Lambda
<Func<Books, bool>>(predicateBody12, new ParameterExpression[] { pe11 });
var qq1 = queryableTestData.Where(condition2);
}
}
}
Exception Message:- {"Instance property 'Heading' is not defined for type >'System.Collections.Generic.List`1[XMLStorageAndFilter.Page]'"}
StackTrace:-
at System.Linq.Expressions.Expression.Property(Expression expression, String propertyName)
at XMLStorageAndFilter.Program2.Main() in c:\Users\Administrator\Documents\Visual Studio 2013\Projects\XMLStorageAndFilter\NavProperty.cs:line 61
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Heading
is not a property ofList<Page>
. It's a property ofPage
, so you're missing a step from the list to each instance. Your declaration ofList<Page> Page
will be misleading. Make itList<Page> Pages
and you should be closer. – KearnsList<Page> Pages
andvar page1 = Expression.Property(pe11, "Pages"); left11 = Expression.Property(page1, "Heading");
– Secondbestpage1
topages
to match its type you'll be able to see more clearly that you're trying to get aHeading
from aList<Page>
. You want to be checking the heading from each page, not from the collection of them. – Kearns