returning an ObjectQuery<T> from the objectQuery using reflection - entity-framework

I have one method which is returning the object of ObjectQuery in this ObjectQuery object the type of object is ObjectQuery, now i want to include table in this object
using reflection, i called the method Include using reflection for this but i m getting the error can someone please tell me the error. here is the sample code.
ObjectQuery objTest = LoadEntitiy(entites,entityClassType);
public ObjectQuery LoadEntitiy(ClientEntities entities, Type entityClasstype)
{
PropertyInfo pi = entities.GetType().GetProperties().First(item => item.Name == entityClasstype.Name.ToString());
Object obj = pi.GetValue(entities, null);
Type objContext = obj.GetType();
return (ObjectQuery)obj;
}
now i m calling the method for including it using the reflection that is here
Type lstType = typeof(ObjectQuery<>);
Type constructedType = lstType.MakeGenericType(typeof(ObjectQuery<>));
MethodInfo addListItemMethod = constructedType.GetMethod("Include");
addListItemMethod.Invoke(objTest, new object[] {"tablename" });

It seems that you want to define a convention to always "Include" a certain set of data.
This convention is normally known as eager loading and there are alternatives like lazy loading.
EF 4.1 or greater already includes functionality to do this for you, see http://msdn.microsoft.com/en-us/library/gg715120(v=vs.103).aspx

Type lstType = typeof(ObjectQuery<>);
Type constructedType = lstType.MakeGenericType(typeof(T(which u want to send as parameter)));
MethodInfo addListItemMethod = constructedType.GetMethod("Include");
object objtest = addListItemMethod.Invoke(objTest, new object[] {"tblname" });
Now the objtest contains the all the table names which you want to include.

Related

Why Class.java don't provide methods like `Type getType()` and `Type getGenericType()`?

Why I have to define a subclass to get the Type of superclass' generic param? Is the limit necessary?
I read the code of Fastjson of Alibaba and tried to figure out why use TypeReference must create an anonymous subclass. Then I found that an object cannot get its own generic param Type even its own Type.
public class TypeReference {
static ConcurrentMap<Type, Type> classTypeCache
= new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);
protected final Type type;
protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type cachedType = classTypeCache.get(type);
if (cachedType == null) {
classTypeCache.putIfAbsent(type, type);
cachedType = classTypeCache.get(type);
}
this.type = cachedType;
}
// ...
}
Sorry for my poor English. Thanks for your answers.
Because of Type Erasure.
Consider the following example
List<String> stringList = new ArrayList<>();
List<Number> numberList = new ArrayList<>();
System.out.println(stringList.getClass() == numberList.getClass());
This will print true. Regardless of the generic type, both instances of ArrayList have the same class and a single Class object. So how could this single Class object return the right Type for both objects?
We can even get a step further,
List<String> stringList = Collections.emptyList();
List<Number> numberList = Collections.emptyList();
System.out.println(stringList == (Object)numberList);
Objects do not know their generic type. If a collection is immutable and always empty, it can be used to represent arbitrary empty lists. The same applies to stateless functions
Function<String, String> stringFunction = Function.identity();
Function<Number, Number> numberFunction = Function.identity();
System.out.println(stringFunction == (Object)numberFunction);
Prints true (on most systems; this is not a guaranteed behavior).
Generic types are only retained in some specific cases, like the signatures of field and method declarations and generic super types.
That’s why you need to create a subclass to exploit the fact that it will store the declared generic supertype. While it sometimes would be useful to construct a Type instance in a simpler way and a suitable factory method can be regarded a missing feature, getting the actual generic type of an arbitrary object (or its Class) is not possible in general.

How does Entity Framework Core handle instances before context is saved?

How does Entity Framework work when something like the following occurs:
var myInstance = new MyObject();
// Do stuff
_myContext.MyObjects.Add(myInstance);
myInstance = null;
_myContext.SaveChanges();
I ran into this happening in a complex foreach-call and it still seem to do what was expected. But I am curious how it handles it and if it gives up tracking the object when the instance is null.
I am curious how it handles it and if it gives up tracking the object when the instance is null
In your example, the instance is not null - just the variable myInstance value is null, i.e. the variable does not hold reference to the object you've created.
What about how EF Core tracks the instances, in simplified form you can think of that as MyObjects being a List<MyObject> (the actual implementation of course is different). So what happens when you do something like this:
var myObjects = new List<MyObject>();
var myInstance = new MyObject();
// Do stuff
myObjects.Add(myInstance);
myInstance = null;
myInstance variable is null, but myObjectList holds a reference to the created object (i.e. is "tracking" it), so it can always be get back, in this case with
var trackedInstance = myObjects[0];
Again, the actual implementation is different, but the concept is the same - the DbContext instance contains some sort of a list with all "tracked" entity instances and their state (Added, Deleted, etc.).

Can't use string.Format() in Anonymous Type

I'm hoping to achieve something as follows:
var comboBoxItems = from state in states
select new
{
Key = state.Code,
Value = string.Format("{0} ({1})", state.Name, state.Code)
};
this.stateComboBox.DisplayMember = "Value";
this.stateComboBox.ValueMember = "Key";
this.stateComboBox.DataSource = new BindingSource(comboBoxItems, null);
However, it gives me the following error when it attempts to bind to the DataSource:
"LINQ to Entities does not recognize the method 'System.String
Format(System.String, System.Object, System.Object)' method, and this
method cannot be translated into a store expression."
Is there any way to include a method like string.Format() in the Anonymous Type?
var comboBoxItems = from state in states.ToList()
select new
{
Key = state.Code,
Value = string.Format("{0} ({1})", state.Name, state.Code)
};
You cannot use Format in LINQ 2 Entities as it cannot be translated to SQL. A call to ToList will cause the items to be loaded from DB and your format will now execute properly.

EF1: Filtering derived types of entity class using .OfType<> by passing a string value

I have a situation where I'm trying to filter a LINQ select using a derived sub class.
ctx.BaseEntity.OfType<SubClass>() - this works fine.
However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.
So what I'd like to do is this:
Perform a projected Select where I
return just the SubClassType from
the database
Perform a second select
using this value as the OfType to
only select the relevant related
entity from the database (No mass
unions generated)
int id = 1;
var classType = (from c in ctx.BaseClass.Include("ClassType")
where c.id == id
select new
{
c.ClassType.TypeName
}).First();
BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id);
But obviously this won't work because OfType requires a Type and not a string.
Any ideas on how I can achieve this?
Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.
So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?
BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "]) as c")
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id).FirstOrDefault();
To answer the headline question about calling OfType with a string / runtime type, you can do the following:
// Get the type, assuming the derived type is defined in the same assembly
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
.Assembly
.GetType("Namespace." + derivedTypeName);
// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });
Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.

Entity Framework Foreign Key Queries

I have two tables in my entity framework, objects, and parameters which have a foreign key pointing to the object to which they belong. I want to populate a tree with all the attributes of a certain object. So in order to find those I want to do this:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT == parentObject
select o);
However when I try to do this I get an error saying it cannot convert from type OBJECT to string, even though in the database this value is stored as a string. I have a workaround where I get an instance of the parentObject, then go through every attribute and check whether it's parent_object == parentObjectInstance, but this is much less efficient than just doing 1 query. Any help would be greatly appreciate, thanks!
Well, PARENT_OBJECT.ToString() can't be called (implicitly or explicitly) in L2E, but if it just returns a property, you can look at that directly:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT.NAME == parentObject
select o);
...note the .NAME
Try this:
String parentObject = "ParentObjectName";
var getAttributes = (from o in myDB.ATTRIBUTE
where o.PARENT_OBJECT.ToString() == parentObject
select o);