开发者

Generically return an item from Entity Framework

开发者 https://www.devze.com 2023-02-12 12:57 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消