2012-07-03 2 views
1

Возможно, вопрос с глупым ответом, но: есть ли способ определить IQueryable, а затем повторно использовать его в разных контекстах позже?IQueryable: повторное использование запроса в другом контексте

Somethink как (псевдокод):

public IQueryable<myItem> MyQuery() 
{ 
    using(MyContext context = new MyContext()) 
    { 
     return (from myItem in context.MyItems 
       select ...); 
    } 
} 

Это будет использоваться в 'некоторых' способом, как показано ниже.

public void MyMethod() 
{ 
    using(MyContext context = new MyContext()) 
    { 
     context.ExecuteQueryUnderContext(MyQuery()); 
    } 

    using(MyContext context2 = new MyContext()) 
    { 
     context2.ExecuteQueryUnderContext(MyQuery()); 
    } 
} 

Благодаря

ответ

1

Я бы передать контекст в качестве параметра для метода Query

public IQueryable<myItem> MyQuery(MyContext context) 
{ 

     return (from myItem in context.MyItems 
       select ...); 
} 

public void MyMethod() 
{ 
    using(MyContext context = new MyContext()) 
    { 
     var query = MyQuery(context); 
    } 
} 
+0

Это было мое мнение тоже. Я думаю, что такой подход обеспечит максимальную гибкость. – Mauro

+0

Этот подход действительно работает, однако он не обеспечивает максимальной гибкости - не позволяет цепочки запросов. –

+0

@ DannyVarod - Я не понимаю, что вы имеете в виду. Я использую этот метод для цепочки запроса несколько раз – Aducci

1
public static class Extension 
    { 
     public static IQueryable<MyItem> MyQuery(this IQueryable<MyItem> items, int someId) 
     { 
      return items.Where(x => x.ID == someId); 
     } 
    } 

использовать его:

using(MyContext context = new MyContext()) 
{ 
     var item = context.MyItems.MyQuery(5); 
} 
2

вы могли бы использовать скомпилированные запросы;

public static readonly Func<MyContext, IQueryable<MyItem>> dbGetMyItems = 
CompiledQuery.Compile<MyContext, IQueryable<MyItem>> 
(context) => from myItem in context.MyItems 
       select ...); 

а затем называть его похожим;

public void MyMethod() 
{ 
    using(MyContext context = new MyContext()) 
    { 
     var query = dbGetMyItems(context); 
    } 
} 

Это также дает преимущество в кэше плана запроса и, таким образом, повышение производительности

2

можно определить запрос в виде функции по неизвестному существующему запросу:

// You can add any paramaters you want to this method 
// You can also turn this into an extension method 
public Func<IQueryable<TItem>, IQueryable<TItem>> MyQuery() 
{ 
    return (IQueryable<TItem> items) => (items.Select...); 
} 

Затем его использовать как это:

using (var context = new MyContext()) 
{ 
    return MyQuery(context.Items).ToList(); 
} 

Или так:

using (var context = new MyContext()) 
{ 
    return MyQuery(context.Items.Where(item.Size > 3)).FirstOrDefault(); 
} 

Таким образом, вы можете повторно использовать и даже запросить цепочку.

Или даже так:

public Item GetItem(Func<IQueryable<TItem>, IQueryable<TItem>> query) 
{ 
    using (var context = new MyContext()) 
    { 
     return query(context.Items).SingleOrDefault(); 
    } 
} 
0

Вы можете использовать мой помощник для:

public static class QueryHelper 
{ 
    static object Get_FieldValue(object obj, string name, bool isBase) 
    { 
     if (isBase) 
     { 
      var _internalContext2 = obj.GetType().BaseType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 
      return _internalContext2.GetValue(obj); 
     } 
     var _internalContext = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 
     return _internalContext.GetValue(obj); 
    } 

    static FieldInfo Get_Field(object obj, string name, bool isBase) 
    { 
     if (isBase) 
     { 
      var _internalContext2 = obj.GetType().BaseType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 
      return _internalContext2; 
     } 
     var _internalContext = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 
     return _internalContext; 
    } 

    static object Get_PropertyValue(object obj, string name, bool isBase) 
    { 
     if (isBase) 
     { 
      var _internalContext2 = obj.GetType().BaseType.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
      return _internalContext2.GetValue(obj); 
     } 
     var _internalContext = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
     return _internalContext.GetValue(obj); 
    } 

    static PropertyInfo Get_Property(object obj, string name, bool isBase) 
    { 
     if (isBase) 
     { 
      var _internalContext2 = obj.GetType().BaseType.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
      return _internalContext2; 
     } 
     var _internalContext = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
     return _internalContext; 
    } 

    public static void SetInternalContextOfQuery(object old, object newobj) 
    { 
     var _internalQuery = Get_Field(old, "_internalQuery", false); 
     var value = _internalQuery.GetValue(old); 
     var _internalContext = Get_Field(value, "_internalContext", false); 
     var _newInternalContext = Get_Property(newobj, "InternalContext", false); 
     var _internalContextValue = _newInternalContext.GetValue(newobj); 

     _internalContext.SetValue(value, _internalContextValue); 

     var _ObjectContext = Get_Property(_internalContextValue, "ObjectContext", false); 
     var _ObjectContextValue = _ObjectContext.GetValue(_internalContextValue); 

     var _objectQuery = Get_Field(value, "_objectQuery", false); 
     var _objectQueryValue = _objectQuery.GetValue(value); 

     var _providerProperty = Get_Property(_objectQueryValue, "ObjectQueryProvider", false); 
     var justV = _providerProperty.GetValue(_objectQueryValue); 

     var _provider = Get_Field(_objectQueryValue, "_provider", true); 
     var _providerValue = _provider.GetValue(_objectQueryValue); 
     var _provider_context = Get_Field(_providerValue, "_context", false); 

     var context = Get_Property(_objectQueryValue, "Context", false); 

     _provider_context.SetValue(_providerValue, _ObjectContextValue); 

     var _query = Get_Property(_objectQueryValue, "QueryState", false); 
     var _queryValue = _query.GetValue(_objectQueryValue); 
     var _query_context = Get_Field(_queryValue, "_context", true); 

     //context.SetValue(_objectQueryValue, _ObjectContextValue); 

     _query_context.SetValue(_queryValue, _ObjectContextValue); 

     var expersionProperty = Get_Property(value, "Expression", false); 
     var expersion = (System.Linq.Expressions.MethodCallExpression)Get_PropertyValue(value, "Expression", false); 
     var result = System.Linq.Expressions.Expression.Lambda(expersion).Compile(); 
     var target = (System.Runtime.CompilerServices.Closure)Get_PropertyValue(result, "Target", false); 
     var exProvider = Get_FieldValue(target.Constants[0], "_provider", true); 
     var exProviderField = Get_Field(exProvider, "_context", false); 

     exProviderField.SetValue(exProvider, _ObjectContextValue); 

     var ex_queryProvider = Get_PropertyValue(target.Constants[0], "QueryState", true); 
     var ex_queryProviderField = Get_Field(ex_queryProvider, "_context", true); 
     //System.Linq.Expressions.Expression.Call() 
     ex_queryProviderField.SetValue(ex_queryProvider, _ObjectContextValue); 

     var ObjectQuery = Get_PropertyValue(value, "ObjectQuery", false); 
     var QueryState = Get_PropertyValue(ObjectQuery, "QueryState", false); 
     var _expression = Get_Field(QueryState, "_expression", false); 
     var a = expersion.Arguments.ToArray(); 
     List<System.Linq.Expressions.ConstantExpression> items = new List<System.Linq.Expressions.ConstantExpression>(); 
     foreach (var item in ((System.Runtime.CompilerServices.Closure)result.Target).Constants) 
     { 
      items.Add(System.Linq.Expressions.Expression.Constant(item)); 
     } 
     System.Linq.Expressions.MethodCallExpression methodCall = 
      System.Linq.Expressions.Expression.Call(expersion.Method, items); 

     //var exV= System.Linq.Expressions.Expression.Lambda(methodCall); 
     _expression.SetValue(QueryState, methodCall); 
    } 
} 

Использование:

    IQueryable<DataBase.Models.UserInfo> query = null; 
        using (var context = new HealthFamilyContext(false)) 
        { 
         query = from p in context.UserInfoes where p.Id == 1 select p; 
        } 

        using (var context = new HealthFamilyContext(false)) 
        { 
         QueryHelper.SetInternalContextOfQuery(query, context); 

         var data = query.ToList(); 
        } 
Смежные вопросы