如何保存和重用IQueryable,或者它的Where子句?

时间:2015-02-12 10:35:15

标签: c# linq

我有一个IQueryable,它有一个带有许多参数的Where子句。我可以将每个参数保存到ASP.NET会话并从零重新创建IQueryable,但我认为更容易只为会话保存一个参数:IQueryable或至少IQueryable的where子句。 怎么做?

查询:

IQueryable<DAL.TradeCard> data = dc.TradeCard.Include("Address").Include("Vehicle");
data = data.Where(it =>
      (tbOrderNumber.Text == null || it.orderNumber == tbOrderNumber.Text) &&
      (tbPlateNumber.Text == null || it.Vehicle.plateNumber == tbPlateNumber.Text));

(现在只有2个,但会有更多参数)

PS:我不想将查询结果保存到会话中。

2 个答案:

答案 0 :(得分:0)

我不确定这是否有效,但您可以尝试使用DataContext.GetCommand获取查询的SQL命令,然后将其保存以与DataContext.ExecuteQuery一起使用。

答案 1 :(得分:0)

我准备好了全部答案,但我误解了你想要实现的目标:)

好的,让我写出我认为你想要做的事情:

  • 服务器获取请求(&#34;获取paramA = 1的数据,paramB = 2,... paramZ = 24&#34;)
  • 服务器运行一系列&#34;其中&#34;并获得过滤结果集
  • 服务器将数据发送到客户端
  • 客户端会对同一组过滤数据进行操作。但是你不希望服务器重新运行查询!并且您无法将数据保存到客户的会话中,因为它有很多记录。
  • 在客户端明确地使用不同的参数调用查询之前,不应重新运行查询

我最近正在研究simillar问题,但是没有一个神奇的子弹:)

解决方案的一些想法:

  1. ID的缓存列表。除非数据进入数十万条记录,否则您可以将所选项目的索引ID保存到会话中。它是什么,每个ID +开销4-8个字节?但这确实会更有效地重新运行查询:data = source.Include("...").Where(i => IdsFromSession.Contain(i.Id));
  2. (在编辑中添加)缓存查询输入字符串/ object /但是会传递您的搜索值。您可以相当容易地对其进行序列化,并将其(或其哈希值)用作服务器端缓存键。
  3. (我喜欢这个主意,但它有点不稳定:))缓存Wheres!现在,这样工作:
    1. 创建采用表达式而不是Funcs
    2. 的方法
    3. 将你的lambda写入该方法,并让该魔法方法实际返回Funcs为&#34; Where&#34;
    4. 获取lambdas
    5. 的唯一哈希值
    6. 检查服务器端缓存中是否有该哈希值,如果需要,运行查询并将结果保存在该哈希值下。
  4. 现在,这是一个巨大的矫枉过正和过度设计的解决方案,但我个人很想实际实现这一点。它看起来像这样:

    class MagicClass{ // don't have time for name-inventing :)
        private List<string> hashes = new List<string>();
        public string Hash {get{ return String.Join("_", hashes);}}
        public Func<TIn,bool> MagicWhere(Expression<Func<TIn,bool>> where){
            var v = new MagicExpressionVisitor();
            v.Visit(where);
            hashes.Add(v.ExpressionHash);
            return where.Compile(); // I think that should do...
        }
    }
    
    class MagicExpressionVisitor : ExpressionVisitor
    {
         public string ExpressionHash {get;set;}
         // Override ExpressionVisitor methods to get a possibly unique hash depending on what's actually in that expression
    }
    

    用法:

    var magic = new MagicClass();
    data = data.Where(magic.MyWhere<DAL.TradeCard,int>(it => it.IsSomething && it.Name != "some name"));
    
    if(!Cache.HasKey(magic.Hash))
        Cache[magic.Hash] = data.ToList();
    return Cache[magic.Hash];
    

    这显然未经测试,但可行。如果已经运行了此类查询(在缓存期间),它将无法在数据源上执行Wheres。它比缓存Id有两个优点:1。它同时适用于许多客户端(因此第二个客户端将受益于第一个请求相同查询的事实,2。它不会触及数据源一点都不。

    如果数据源是DB,您可以找出正在运行的实际SQL命令是什么,SHA - ### it并在该哈希下保存结果,但我的疯狂解决方案适用于其他数据源,如LINQ-to-对象等;)