I have the following code that builds an IQueryable
Expression<Func<TParentEntity, TChildEntity, bool>> joinExpr =
ctx.GetJoinExpression<TParentEntity, TChildEntity>();
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity>(ctx);
return
from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
let childEntities =
from child in ctx.GetQueryable<TChildEntity>()
where joinExpr.Invoke(parentEntity, child)
select child
where childEntities.Any(childSelectionExpression)
select parentEntity;
I've been trying (unsuccesfully) build the expression tree that would return the same result.
I would like to have an expression Expression<Func<TParentEntity,bool> parentExpression
that i could use as following:
from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
where parentExpression.Invoke(parentEntity)
select parentEntity
Does anybody think this is possible? I believe so, but i am unable to solve it...
I know what you want and because I have tries it, I am sorry to inform you that you have arrived in a world of pain. Here is a partial workaround:
Expression<Func<TParentEntity, TChildEntity, bool>> joinExpr =
ctx.GetJoinExpression<TParentEntity, TChildEntity>();
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity>(ctx);
return
(from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
let childEntities =
from child in ctx.GetQueryable<TChildEntity>()
where joinExpr.Invoke(parentEntity, child)
select child
select parentEntity).Where(childSelectionExpression);
You have to transform all query calls that use expression variable like I did it. Not always possible but I think in your case it is.
Eureaka :-)
The method at the end of this post returns an expression of type Expression<Func<TParentEntity,bool>>, let's call that one the parentExpression.
When used like this:
var data = (from parentEntity in parentEntities.AsExpandable()
where parentExpression.Invoke(parentEntity) select parentEntiy).ToList()
What happens is actually something like this:
var data = (from parentEntity in parentEntities.AsExpandable()
let childeren = childEntities.Where(c => c.parentId = parentEntity.Id)
where childeren.Any([childSelectionLambda])
select parent).ToList()
By being able to express the child criteria in one Lambda of type
Expression<Func<TParentEntity, bool>>
it is easy to combine multiple child criteria (which are expressed as parent criteria) or other (normal) parent criteria using PredicateBuilder.And().
Tests are green for EF and linq to SQL (and sql ce) :-)
override public Expression<Func<TParentEntity, bool>>
GetParentExpression<TParentEntity>( IDynamicQueryAdapter ctx )
{
// Define parameters needed in expresion tree
ParameterExpression parentParameter =
Expression.Parameter (typeof (TParentEntity), "parent");
ParameterExpression childParameter =
Expression.Parameter (typeof (TChildEntity), "child");
// Define the IQueryable<TChildEntity> as
// a constant for use in the expression tree.
IQueryable<TChildEntity> childDatasource =
ctx.GetQueryable<TChildEntity>().AsExpandable();
ConstantExpression childDatasourceConstant =
Expression.Constant (childDatasource);
// Get MethodInfo instance, needed for the MethodCallExpression
MethodInfo anyMethodInfoChildEntity =
QueryHelper.GetQueryableAnyMethod<TChildEntity> ();
// Get the lambda expression
// required to select only those child entities
// which meet the user defined criteria
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity> (ctx);
// Use the ExpressionParameter childParamter for the
// ChildSelectionExpression and strip Expression.Invoke using Expand()
Expression<Func<TChildEntity, bool>> lambda5 =
Expression.Lambda<Func<TChildEntity, bool>> (
Expression.Invoke (childSelectionExpression, childParameter),
childParameter).Expand ();
#region Express the parent child relation
PropertyInfo parentKeyPropertyInfo = null;
PropertyInfo childKeyPropertyInfo = null;
ctx.GetParentChildAssociationProperties (
typeof (TParentEntity), typeof (TChildEntity),
out parentKeyPropertyInfo, out childKeyPropertyInfo);
Expression parentPropertyExpression =
Expression.Property (parentParameter, parentKeyPropertyInfo.Name);
Expression childPropertyExpression =
Expression.Property (childParameter, childKeyPropertyInfo.Name);
if( childKeyPropertyInfo.PropertyType != parentKeyPropertyInfo.PropertyType )
{
// TODO: what if the property types are incomparable >> exception.
// some more code is needed!!
Type nullableParentType =
typeof (Nullable<>)
.MakeGenericType (parentKeyPropertyInfo.PropertyType);
if( childKeyPropertyInfo.PropertyType == nullableParentType )
{
childPropertyExpression =
Expression.Convert (childPropertyExpression,
parentKeyPropertyInfo.PropertyType);
}
else if( childKeyPropertyInfo.PropertyType.IsValueType )
{
Type nullableChildType =
typeof (Nullable<>).MakeGenericType (childKeyPropertyInfo.PropertyType);
if( parentKeyPropertyInfo.PropertyType == nullableChildType )
{
parentPropertyExpression =
Expression.Convert (parentPropertyExpression,
childKeyPropertyInfo.PropertyType);
}
}
}
#endregion
var lambda4 = Expression.Lambda<Func<TChildEntity, bool>> (
Expression.Equal (
parentPropertyExpression,
childPropertyExpression), childParameter );
var predicate = lambda4.And(lambda5).Expand();
Expression<Func<TParentEntity, bool>> parentSelectionExpression =
Expression.Lambda<Func<TParentEntity,bool>>(
Expression.Call (
null,
anyMethodInfoChildEntity,
new Expression[] { childDatasourceConstant, predicate }),
new[]{parentParameter});
return parentSelectionExpression;
}
note: PredicateBuilder, extension AsExpandable(), extenstion Expand() ... are part of LinqKit
For more info about those visit: Linqkit into
Related
i try to query (linq to entities EF Core) a navigation properties collection, so i use any() like this :
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(p => p.myprop == myvar );
It's work perfectly but now i want to construct the predicate and not defined it directly in the query.
so i do :
Func<T, bool> mypredicate = (p => p.myprop == myvar);
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(mypredicate);
(I have replace T by my entity name)
but this generate an error : Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
How can i construct my predicate to use it on Any() collection ?
Thank's
This line for example:
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(p => p.myprop == 1));
When compiled will be compiled to something like this:
var xParameter = Expression.Parameter(typeof(Entity1), "x");
var pParameter = Expression.Parameter(typeof(Entity2), "p");
var anyMethod =
typeof(Enumerable)
.GetMethods()
.Single(x => x.Name == "Any" && x.GetParameters().Length == 2)
.MakeGenericMethod(typeof(Entity2));
var anyCondition = Expression.Lambda<Func<Entity2, bool>>(
Expression.Equal(
Expression.Property(
pParameter,
typeof(Entity2).GetProperty("myprop").GetMethod),
Expression.Constant(1, typeof(int))),
pParameter);
var query = context.MyTable.Where(
Expression.Lambda<Func<Entity1, bool>>(
Expression.Call(
null,
anyMethod,
new Expression[] {
Expression.Property(
xParameter,
typeof(Entity1).GetProperty("mycollectionproperties").GetMethod),
anyCondition
}),
xParameter));
This is called an expression tree. See this reference for more details:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/
Although the Any method takes a Func, when constructing the expression tree, notice that an expression (Expression<Func<Entity2, bool>>) is given to the Any method.
There doesn't seem to be a way from C# to give the Any method an expression instead of a Func even if the whole thing is an expression tree (I mean in a parameterized way like you want to achieve).
The most obvious way to achieve what you want is to use the code from this post and replace the anyCondition variable with whatever expression you want to use for the condition inside Any.
Another way is to construct part of the expression tree "normally" and pass null to the Any method and then use an expression visitor to replace the null with your expression. Here is how such visitor would look like:
public class AnyMethodArgumentReplacingVisitor : ExpressionVisitor
{
private readonly Expression expression;
public AnyMethodArgumentReplacingVisitor(Expression expression)
{
this.expression = expression;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == "Any")
{
return Expression.Call(node.Object, node.Method, node.Arguments[0], expression);
}
return base.VisitMethodCall(node);
}
}
Here is how you would use it:
Expression<Func<Entity2, bool>> predicate =
a => a.myprop == 2;
Expression<Func<Entity1, bool>> expression =
b => b.mycollectionproperties.Any(null);
var expression2 =
(Expression<Func<Entity1, bool>>)
new AnyMethodArgumentReplacingVisitor(predicate).Visit(expression);
Please note that such visitor would replace the call to any Any method. It also assumes that only the overload of Any that takes a predicate is used. There is another overload of Any that does not take a predicate. If you need to use that, you need to adjust the code.
It looks to me your problem is in your definition of
Func<T, bool> mypredicate = (p => p.myprop == myvar);
You should not use T, you should use the type of mycollectionproperties
Assuming the property mycollectionproperties is defined as something like this
....
public IQueryable<YourType> mycollectionproperties { get; set; }
....
Then you should declare mypredicate as
Func<YourType, bool> mypredicate = (p => p.myprop == myvar);
You can see a working sample on .NetFiddle
I have a method to insert entity to tables genericly using type T. But I want to add a feature to check if the entity to be added exists in the table based on a matcher property (e.g Name). When I execute the code it throws 'has no supported translation to SQL' on the check line. My code part is below. How can I fix this problem?
public static InsertStatus Add<T>(T ent, string matcherProp) where T : class
{
System.Data.Linq.Table<T> t = otdc.GetTable<T>();
//Exception on this line
if (t.Any(item => object.Equals(GetPropValue(item, matcherProp), GetPropValue(ent, matcherProp))))
return InsertStatus.AlreadyExists;
try
{
t.InsertOnSubmit(ent);
otdc.SubmitChanges();
return InsertStatus.Successfull;
}
catch
{
return InsertStatus.UnknownError;
}
}
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
You will need to create an expresion tree at runtime. Fortunately this isn't very hard in your case; it will be something like:
var p = Expression.Parameter(typeof(T), "p");
var val = GetPropValue(ent, matcherProp);
var test = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.PropertyOrField(p, matcherProp),
Expression.Constant(val)
), p);
if (t.Any(test))
return InsertStatus.AlreadyExists;
What this does is construct the logical tree for:
p => p.{matcherProp} == {val}
where matcherProp is the name of the member to test, and val is the existing value as a constant.
Note that you might get issues if val is null, unless you can also supply the type of the property (.PropertyType on the PropertyInfo) - and supply it to Expression.Constant.
Edit: another way to do this is to supply ent as the constant:
var p = Expression.Parameter(typeof(T), "p");
var test = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.PropertyOrField(p, matcherProp),
Expression.PropertyOrField(Expression.Constant(ent), matcherProp),
), p);
This is then more akin to:
p => p.{matcherProp} == ent.{matcherProp}
where ent in the lambda behaves much like a "captured variable".
Instead of making matcherProp a string, consider making it an Expression<Func<T, P>> so you can invoke it as: Add(myEntity, e => e.Name).
Then you need something like
public static InsertStatus Add<T>(T ent, Expression<Func<T,P>> keySelector) where P : class
{
System.Data.Linq.Table<T> t = otdc.GetTable<T>();
var memberAccess = (keySelector as LambdaExpression)?.Body as MemberExpression;
ParameterExpression paramExpr = Expression.Parameter(typeof(T), "e");
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T,bool>>(
Expression.Equal(memberAccess.Update(Expression.Constant(ent)), memberAccess.Update(paramExpr)), paramExpr);
if (t.Any(predicate))
{
With appropriate error checking of course.
I have the search function. and I want to select all value in my Book table which contain _searchdata but I dont know how to express at "where" with the short code instead of listing all items of Table like this:
(I just get some items for example, it contains about 100 items like Booktitle, Author, Genre... i dont want to specify it because it's so long)
public void SearchAny(string _searchdata)
{
var searchAnyInDB = from Book x in BookDB.Books
where (x.BookTitle.Contains(_searchdata)
|| x.Author.Contains(_searchdata)
|| x.Genre.Contains(_searchdata))
select x;
DataSearch.Clear();
DataSearch = new ObservableCollection<Book>(searchAnyInDB);
}
Because LINQ to Entities and LINQ to SQL both use Expression<Func<TSource, bool>> as IQueryable.Where extension method parameter, you can use reflection to create that Expression during compile type and generate all there || instead of typing them into your source code.
Would be something like:
var searchAnyInDB = from Book x in BookDB.Books
where (GetWhereExpression<Book>(_searchdata))
select x;
And GetWhereExpression<TSource> method:
static Expression<Func<TSource, bool>> GetWhereExpression<TSource>(string value)
{
var param = Expression.Parameter(typeof(TSource));
var val = Expression.Constant(value);
var expression = Expression.Equal(Expression.Constant(1), Expression.Constant(1));
foreach(var prop in typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if(prop.PropertyType == typeof(string))
{
expression = Expression.OrElse(expression,
Expression.Call(
Expression.Property(param, prop),
"Contains",
null,
val
)
);
}
}
return Expression.Lambda<Func<TSource, bool>>(expression, param);
}
You still can do better then that, ex. remembering the expression for type to prevent using reflection every time you need to execute the query with different search texts, etc. But it should give you an idea where to go.
I'm building a filtering system for UserProfiles based on known properties but unknown (until runtime) combination of filtering conditions.
In my previous question How do I create a generic Expression that has an expression as a parameter, I've figured out a way to have a FilterDefinition for any value property reachable from User entity via navigation properties (i.e. (User)u=> u.NavigationProperty.AnotherNavigationProperty.SomeValue)
and I have a method that can return a predicate as Expression<Func<User,bool>> for a given property, operation ( > < == etc ) and a value.
Now the time has come to filter them on collection properties as well.
Say for example User has CheckedOutBooks collection (which is a total fiction, but will do)
And I need to create a filter definition for Name property of CheckedOutBooks collection on User object.
What I have:
A collection of Users
User class has a collection of Books
now I would like to create a method
Expression<Func<User,bool>> GetPredicate(Expression<User,TProperty>, Operations operation, TProperty value)
That I can call like GetPredicate(u=>u.Books.Select(b=>b.Name), Operations.Contains, "C# in a nutshell")
and get an expression back similar to
u=>u.Books.Any(b=>b.Name == "C# in a nutshell")
I'm thinking maybe it will be easier to split first parameter in two to achieve this.
Maybe u=>u.Books and b=>b.Name will do better?
EDIT:
what I got so far:
class FilterDefinitionForCollectionPropertyValues<T>:FilterDefinition, IUserFilter
{
public Expression<Func<UserProfile, IEnumerable<T>>> CollectionSelector { get; set; }
public Expression<Func<T, string>> CollectionPropertySelector { get; set; }
public Expression<Func<Profile.UserProfile, bool>> GetFilterPredicateFor(FilterOperations operation, string value)
{
var propertyParameter = CollectionPropertySelector.Parameters[0];
var collectionParameter = CollectionSelector.Parameters[0];
// building predicate to supply to Enumerable.Any() method
var left = CollectionPropertySelector.Body;
var right = Expression.Constant(value);
var innerLambda = Expression.Equal(left, right);
Expression<Func<T, bool>> innerFunction = Expression.Lambda<Func<T, bool>>(innerLambda, propertyParameter);
var method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(T));
var outerLambda = Expression.Call(method, Expression.Property(collectionParameter, typeof(UserProfile).GetProperty("StaticSegments")), innerFunction);
throw new NotImplementedException();
}
}
Now this one works awesomely and does exactly what's needed, now the only thing I need to figure out is how to replace typeof(UserProfile).GetProperty("StaticSegments")) somehow to use CollectionPropertySelector that is in current example would be (UserProfile)u=>u.StaticSegments
You're almost done. Now you just need to do a little trick - wrap your CollectionPropertySelector lambda expression in the CollectionSelector lambda expression.
Expression<Func<TParent,bool>> Wrap<TParent,TElement>(Expression<Func<TParent, IEnumerable<TElement>>> collection, Expression<Func<TElement, bool>> isOne, Expression<Func<IEnumerable<TElement>, Func<TElement, bool>, bool>> isAny)
{
var parent = Expression.Parameter(typeof(TParent), "parent");
return
(Expression<Func<TParent, bool>>)Expression.Lambda
(
Expression.Invoke
(
isAny,
Expression.Invoke
(
collection,
parent
),
isOne
),
parent
);
}
You may have to change this a bit to be used for your particular scenario, but the idea should be clear. My test looked basically like this:
var user = new User { Books = new List<string> { "Book 1", "Book 2" }};
var query = Wrap<User, string>(u => u.Books, b => b.Contains("Bookx"), (collection, condition) => collection.Any(condition));
So you specify the collection selector, predicate and predicate operator, and you're done.
I've written it as a generic method for clarity, but it's dynamic, not strongly typed in essence, so it should be pretty easy to change it to non-generic, if you need that.
Ok I've got it solved for myself.
And I published it to gitHub:
https://github.com/Alexander-Taran/Lambda-Magic-Filters
Given the filter definition class (not reafactored to support properties other than string so far, but will do later):
class FilterDefinitionForCollectionPropertyValues<T>:FilterDefinition, IUserFilter
{
//This guy just points to a collection property
public Expression<Func<UserProfile, IEnumerable<T>>> CollectionSelector { get; set; }
// This one points to a property of a member of that collection.
public Expression<Func<T, string>> CollectionPropertySelector { get; set; }
//This one does the heavy work of building a predicate based on a collection,
//it's member property, operation type and a valaue
public System.Linq.Expressions.Expression<Func<Profile.UserProfile, bool>> GetFilterPredicateFor(FilterOperations operation, string value)
{
var getExpressionBody = CollectionPropertySelector.Body as MemberExpression;
if (getExpressionBody == null)
{
throw new Exception("getExpressionBody is not MemberExpression: " + CollectionPropertySelector.Body);
}
var propertyParameter = CollectionPropertySelector.Parameters[0];
var collectionParameter = CollectionSelector.Parameters[0];
var left = CollectionPropertySelector.Body;
var right = Expression.Constant(value);
// this is so far hardcoded, but might be changed later based on operation type
// as well as a "method" below
var innerLambda = Expression.Equal(left, right);
Expression<Func<T, bool>> innerFunction = Expression.Lambda<Func<T, bool>>(innerLambda, propertyParameter);
// this is hadrcoded again, but maybe changed later when other type of operation will be needed
var method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(T));
var outerLambda = Expression.Call(method, Expression.Property(collectionParameter, (CollectionSelector.Body as MemberExpression).Member as System.Reflection.PropertyInfo), innerFunction);
var result = Expression.Lambda<Func<UserProfile, bool>>(outerLambda, collectionParameter);
return result;
}
}
I want to create a dynamic linq expression for sql IN clause in EF 6.0 with code first approch. Note that i am new to Expressions. What i want to achive is
select * from Courses where CourseId in (1, 2, 3, 4)
//CourseId is integer
The normal linq query looks like this. But i want to query it dynamically
string[] ids = new string[]{"1", "2", "3", "4"};
var courselist = DBEntities.Courses.Where(c => ids.Contains(SqlFunctions.StringConvert((decimal?)c.CourseId)))
There are two ways to make dynamic expression.
1) one ways is to loop through ids and make expressions
The below code will create the following expression in debug view
{f => ((StringConvert(Convert(f.CourseId)).Equals("23") Or StringConvert(Convert(f.CourseId)).Equals("2")) Or StringConvert(Convert(f.CourseId)).Equals("1"))}
Dynamic Expression is
var param = Expression.Parameters(typeof(Course), "f")
MemberExpression property = Expression.PropertyOrField(param, "CourseId");
MethodInfo mi = null;
MethodCallExpression mce = null;
if (property.Type == typeof(int))
{
var castProperty = Expression.Convert(property, typeof(double?));
var t = Expression.Parameter(typeof(SqlFunctions), "SqlFunctions");
mi = typeof(SqlFunctions).GetMethod("StringConvert", new Type[] { typeof(double?) });
mce = Expression.Call(null,mi, castProperty);
}
mi = typeof(string).GetMethod("Equals", new Type[]{ typeof(string)});
BinaryExpression bex = null;
if (values.Length <= 1)
{
return Expression.Lambda<Func<T, bool>>(Expression.Call(mce, mi, Expression.Constant(values[0]), param));
}
//var exp1 = Expression.Call(mce, mi, Expression.Constant(values[0]));
for (int i = 0; i < values.Length; i++)
{
if (bex == null)
{
bex = Expression.Or(Expression.Call(mce, mi, Expression.Constant(values[i])), Expression.Call(mce, mi, Expression.Constant(values[i + 1])));
i++;
}
else
bex = Expression.Or(bex, Expression.Call(mce, mi, Expression.Constant(values[i])));
}//End of for loop
return Expression.Lambda<Func<T, bool>>(bex, param);
2) The 2nd way that i tried (debug view)
{f => val.Contains("23")} //val is parameter of values above
The dynamic expression for above that i tried is
var param = Expression.Parameters(typeof(Course), "f")
MemberExpression property = Expression.PropertyOrField(param, "CourseId");
var micontain = typeof(Enumerable).GetMethods().Where(m => m.Name == "Contains" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(string));
var mc = Expression.Call(micontain, Expression.Parameter(values.GetType(), "val"), Expression.Constant("2"));//NOTE: I haven't use CourseId for now as i am getting conversion error
return Expression.Lambda<Func<T, bool>>(mc, param);
I get the following errors
LINQ to Entities does not recognize the method 'System.String StringConvert(System.Nullable`1[System.Double])' method, and this
method cannot be translated into a store expression when i use the
first methodology. I know i can't use ToString with EF thats why I used SqlFunctions but it is not working for me.
The parameter 'val' was not bound in the specified LINQ to Entities query expression using 2nd methodology
I am trying this from last 4 days. I googled it but didn't find any suitable solution. Please help me.
After a lot of struggle I found solution to my question.
I want to achieve this sql query
select * from Courses where CourseId in (1, 2, 3, 4)
Using Linq to Entities, but I want to pass in(1,2,3,4) list dynamically to linq query. I created an Extension class for that purpose.
public static class LinqExtensions
{
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> In<T, TValue>(this Expression<Func<T, bool>> predicate,string propertyName, List<TValue> values)
{
var param = predicate.Parameters.Single();
MemberExpression property = Expression.PropertyOrField(param, propertyName);
var micontain = typeof(List<TValue>).GetMethod("Contains");
var mc = Expression.Call(Expression.Constant(values), micontain, property);
return Expression.Lambda<Func<T, bool>>(mc, param);
}
}
Use of LinqExtensions
var pred = LinqExtensions.False<Course>(); //You can chain In function like LinqExtensions.False<Course>().In<Course, int>("CourseId", inList);
var inList= new List<int>(){1, 2, 3}; //Keep in mind the list must be of same type of the Property that will be compared with. In my case CourseId is integer so the in List have integer values
pred =pred.In<Course, int>("CourseId", inList); //TValue is int. As CourseId is of type int.
var data = MyEntities.Courses.Where(pred);
I hope this might be beneficial for some one
have you seen the type of
var courselist = DBEntities.Courses.Where(c => ids.Contains(c.CourseId)))
above statement would not return actual list of courses. The query is not executed yet. It just returns IQuereable. The query is executed when you actually call .ToList() method on it
so, your solution is..
Create array of IDs using for loop and then simply run the below query
var courselist = DBEntities.Courses.Where(c => ids.Contains(c.CourseId))).ToList()