Generically return an item from Entity Framework
I have a situation where a website can ask for data from my database based on a string (don't worry - I开发者_JS百科'm protecting against SQL injections). For various reasons, I would like to have a single method which returns back the object (from EF) that the user expects (which, ultimately, comes back through a partial page).
I'm thinking something like this:
public <GenericType?> GetObject(int id, string typeName) {
switch(typeName) {
case "Type1":
return db.Type1s.SingleOrDefault(t => t.TypeID == id);
case "Type2":
return db.Type2.SingleOrDefault(t => t.TypeID == id);
default:
return null;
}
}
Is it possible to do something like this? (What I am trying to avoid is having to do the switch statement earlier and then call the specific Repository method because I would then have to repeat code and do this a number of times.)
CreateQuery<T>
might be what you need.
Does the Entity Framework have an equivalent of DataContext.GetTable<TEntity> from Linq2Sql (ObjectContext.CreateQuery<T>?)
Is there any way you can get all the possible types you'd be passing in to comport with a particular interface that has this TypeID property on it? If so, how about:
public T GetResult<T>(int id, string typeName) where T : IClassWithTypeID {
YourEntities db = new YourEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeName));
return result.Single(t => t.TypeID == id);
}
Practically speaking, any kind of generalized report generator / query executor / etc. is probably better served with direct SQL queries than trying to fit your dynamic logic into EF or LINQ.
How about
public T GetResult<T>(int id, string typeName) {
AccrualTrackingEntities db = new AccrualTrackingEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeName));
var param = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, "TypeID"),
Expression.Constant(id)),
param);
return result.Single(lambda);
}
I guess manually stringing together an Expression tree isn't as hard as I thought it was.
Considering how things will look when you call this method...presumably it would look something like this:
object obj = GetObject(257, "Type1");
I can't think of a way to make the type of the returned value more specific, because objects in the EF don't have a common base class, neither do they implement a common interface. Of course, you could make them implement such an interface (as Adam suggests, though with a different purpose), and then rewrite your method like this:
public IMyInterface GetObject(int id, string typeName) {
switch(typeName) {
case "Type1":
return (IMyInterface)db.Type1s.SingleOrDefault(t => t.TypeID == id);
case "Type2":
return (IMyInterface)db.Type2.SingleOrDefault(t => t.TypeID == id);
default:
return null;
}
}
Then your calling code would look like this:
IMyInterface intf = GetObject(257, "Type1");
intf.DoSomethingHelpful();
Of course, my guess at your calling code may be way off.
精彩评论