Cast BindingList of interface to filter by dynamic linq query knowing the type - dynamic-linq

I have a bindinglist of type ISomething. That I need to filter with a dynamic linq query.
BindingList<ISomething> myList;
var myType = typeof(MyClass); (MyClass a class that implements ISomething)
I need to be able to cast to a bindinglist of myClass just by knowing the myType.
var result = myList.Cast<something?>.AsQueryable().Where("FilterOption=\"Filter\"");

Your filter description would have to exist in the Interface as a method. ie Description()

Related

Joins in Linq 2 SQL using IDataContext

I've an interface for my dbContext class as follows
public interface IDataContext : IDisposable, IUnitOfWork
{
IQueryable<T> Query<T>() where T : class ;
.... Other methods
}
and my implementation of this is like this
public IQueryable<T> Query<T>() where T : class
{
return Set<T>();
}
Now when I do query like this
var menus = (from s in _dbContext.Query<SiteMenu>()
from r in _dbContext.Query<RoleMenu>()
where r.Role.Name == rolename
select s).ToList();
I got the following error
LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[G.Domain.Models.Models.RoleMenu] Query[RoleMenu] ()' method, and this method cannot be translated into a store expression.
I've to make explicit join to make this work, Can you explain this ?
Even though you have a perfect looking LINQ query like this:
var menus = (from s in _dbContext.Query<SiteMenu>()
from r in _dbContext.Query<RoleMenu>()
where r.Role.Name == rolename
select s).ToList();
If the Query method calls some custom method inside of it, it will be embedded into the logic trying to convert this LINQ query into SQL, and attempt to convert any method calls into an appropriate SQL method. There is limited method support in LINQ, and as such it finds the method "QueryRoleMenu" that it can't convert to SQL, and throws this exception.

How to convert ODataEnumValue into its CLR enum type?

While traversing the expression tree from a FilterQueryOption, I have an instance of a ODataEnumValue. I'm wondering how to convert that into the corresponding CLR enum type value in generic way (i.e. without having to look-up the actual CLR type myself).
Maybe you can refer to ODataEnumDeserializer's ReadInline method, which convert ODataEnumvalue to CLR enum type if it is in EdmModel.
The enum type can be retrieved by getting the ClrTypeAnnotation of the TypeReference as follows. First get the model from the FilterQueryOption instance:
IEdmModel _model = filterQueryOption.Context.Model;
Then, later when parsing its FilterClause, for example for a ConstantNode:
private object GetClrValue(ConstantNode constantNode)
{
ODataEnumValue enumValue;
...
else if ((enumValue = constantNode.Value as ODataEnumValue) != null)
{
var annotation = _model.GetAnnotationValue<ClrTypeAnnotation>(constantNode.TypeReference.Definition);
Type enumType = annotation.ClrType;
parameterValue = Enum.Parse(enumType, enumValue.Value);
}
...
}

Cannot map raw SQL query to DataRow

I am trying to get IEnumerable from linq query below. What am I doing wrong?
IEnumerable<DataRow> results =
context.Database.SqlQuery<DataRow>("SELECT * FROM Customer").AsEnumerable();
DataRow class does not have default (parameterless) constructor, so you can't use it as query parameter type. There is no generic constraints on type parameter, and nothing mentioned on MSDN(!), but column map factory will throw exception if parameter type does not have default constructor:
The result type 'System.Data.DataRow' may not be abstract and must
include a default constructor.
Here is a code which throws this exception:
internal static CollectionColumnMap CreateColumnMapFromReaderAndClrType(
DbDataReader reader, Type type, MetadataWorkspace workspace)
{
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
ConstructorInfo constructor = type.GetConstructor(flags, (Binder) null, Type.EmptyTypes, (ParameterModifier[]) null);
if (type.IsAbstract || (ConstructorInfo) null == constructor && !type.IsValueType)
throw EntityUtil.InvalidOperation(InvalidTypeForStoreQuery((object) type));
// ...
}
BTW Mapping to DataRow makes no sense, even if it would have default public constructor. Because it is not simple primitive type and it does not have properties which match the names of columns returned from the query (yes, mapping uses properties only).
Correct usage of Linq will be
IEnumerable<Customer> results = context.Customers;
That will generate SELECT * FROM Customer query, and map query results to customer entities. If you really want to use raw SQL:
IEnumerable<Customer> results =
context.Database.SqlQuery<Customer>("SELECT * FROM Customers");
I think we were trying to solve the same problem (Google led me here, anyway). I am executing a raw SQL command through SqlQuery<TElement>(string sql, params object[] parameters and wanted to assert individual properties of the results returned from the query in a unit test.
I called the method:
var result = (db.SqlQuery<Customer>("select * from customers").First();
and verified the data it returned:
Assert.AreEqual("John", result.FirstName);
I defined a private class Customer inside my test class (unfortunately, I'm not using Entity Framework):
private class Customer
{
public string FirstName { get; set; }
}
The properties of Customer must match the column names returned in the SQL query, and they must be properties (not just variables of the Customer class. You don't have to create properties for all of the columns returned from the query.

Dynamically pass Type to Method<T>

I've a method , that retrieves to me some data according to some type I passed in parameter, like this :
protected void FillList<TEntity>()
{
doWorkForTEntity();
}
I Need to dynamically call this method :
Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
where entity.Name.Equals(this.targetEntity)
select entity).FirstOrDefault();
FillList<currentEntity>();
I got this error :
The type or namespace name 'currentEntity' could not be found (are you missing a using directive or an assembly reference?)
I've tried an intermediate object type, no success
Any Idea please ?
Since there is no information about entity type in compile time, you need to construct and call appropriate method by reflection:
Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
where entity.Name.Equals(this.targetEntity)
select entity).FirstOrDefault();
var method = this.GetType().GetMethod("FillList", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(currentEntity);
method.Invoke(this, new object[0]);
You need to do that with reflection as well, so it won't fail in compile time (compiler checks):
Generic class:
Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
where entity.Name.Equals(this.targetEntity)
select entity).FirstOrDefault();
Type fillListType= typeof(FillList<>);
Type constructedGenericClass = fillListType.MakeGenericType(currentEntity);
object myList = Activator.CreateInstance(constructedGenericClass );
Generic Method:
Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
where entity.Name.Equals(this.targetEntity)
select entity).FirstOrDefault();
MethodInfo methodinfo = this.GetType().GetMethod("FillList");
MethodInfo genericMethod = method.MakeGenericMethod(currentEntity);
genericMethod.Invoke(this, null);
Type parameters must be specified at compile time and can´t be assigned at runtime like in your example. You get the error message because there´s no Type called currentEntiry since it´s just a variable.
Change your method to take an instance of the Type TEntity:
protected void FillList<TEntity>(TEntity instance)
{
doWorkForTEntity();
}
Create a dynamic instance from the Type name and then call the modified method:
dynamic instance = Activator.CreateInstance(this.targetEntity);
FillList(instance);
The dynamic type is basically doing what the other answers have shown you - but IMHO this code is neater and clearer in its intent.

When selecting an anonymous type with LINQ from EF, is there no way to run a method on an object as you select it?

Let's say I have a method:
bool myMethod(int a)
{
//return a bool
}
So let's say I the following
// assume a has prop1 and prop2 both ints
var mySelection = from a in myContainer
where a=somecondition
select new {
a.prop1,
myMethod(a.prop2)
};
Is there really no way to run myMethod in the anonymous type declaration? Is there some sort of trick?
Can I put an anonymous method in there to return the equivalent of myMethod(a.prop2)?
Well lets separate this into LINQ to Objects and LINQ to Entities
In LINQ to Object the above fails because the compiler doesn't know what the Property name is, if you change it to this:
var mySelection = from a in myContainer
where a=somecondition
select new {
a.prop1,
prop2 = myMethod(a.prop2)
};
It will work in LINQ to Objects
However the Entity Framework won't be able to translate the method call (unless it is a function known to the EF like a Model Defined Function, EdmMethods or SqlMethods) so you'll have to rewrite that query like this:
var mySelection = from a in myContainer
where a=somecondition
select new {
a.prop1,
a.prop2
};
var myResults = from a in mySelection.AsEnumerable()
select new {a.prop1, prop2 = myMethod(a.prop2)};
This pulls what you need out the database, and then using the AsEnumerable() call turns the call to myMethod into something processed by LINQ to Objects rather than LINQ to Entities
Hope this helps
Alex
I don't think there is a way to call out to a method from an anonymous initializer. Even if there were, it probably wouldn't perform very well.
If you need to create a result set that requires additional processing, I would create a concrete class.

Resources