【问题标题】:How to safely and effectively cache ADO.NET commands?如何安全有效地缓存 ADO.NET 命令?
【发布时间】:2008-12-21 15:52:07
【问题描述】:

我想用这个模式:

SqlCommand com = new SqlCommand(sql, con);
com.CommandType = CommandType.StoredProcedure;//um
com.CommandTimeout = 120;
//com.Connection = con;  //EDIT: per suggestions below

SqlParameter par;
par = new SqlParameter("@id", SqlDbType.Int);
par.Direction = ParameterDirection.Input;

com.Parameters.Add(par);

HttpContext.Current.Cache["mycommand"] = com;

显然我不想遇到奇怪的问题,比如人 A 从缓存中检索它,更新 param1,人 2 从缓存中获取它并更新 param2,每个用户运行命令时混合了两者。

克隆从缓存中取出的命令可能比从头创建一个新命令更昂贵。

ASP.NET 缓存的线程安全性如何?我是否错过了任何其他潜在的陷阱?尽管存在线程问题,这种技术是否适用于无参数命令?

澄清:如果我想比喻性地朝自己的脚开枪,我该如何瞄准?有没有办法锁定对缓存中对象的访问以便序列化访问?

【问题讨论】:

    标签: c# .net asp.net vb.net ado.net


    【解决方案1】:

    很简单:不要。如果您看不出这是错误的,您需要在 ADO.NET 上阅读更多内容。有大量文献解释了正确的方法:只需在需要时创建连接和命令,并确保正确处理它们。

    【讨论】:

      【解决方案2】:

      缓存本身是线程安全的,但这并不赋予您放置在其中的对象线程安全性。 SqlCommand 对象不是线程安全的,因此不是您想要缓存的那种东西。

      在这种情况下,最重要的是缓存为您处理的连接,您不应该尝试自己处理。

      与执行相比,命令对象(即使是具有许多参数的对象)的创建仍然是小菜一碟。除非您有相反的证据,否则不要尝试缓存它们。

      项目的最大风险是过早优化。

      【讨论】:

        【解决方案3】:

        正如其他人所说,这只是一个坏主意。这是一个坏主意的原因有很多。

        最重要的是,如果您处于高负载情况下,为每个用户存储命令将很快填满缓存,并且根据优先级等,将开始导致其他项目脱落缓存,它应该真的还在那里。

        使用 ADO.NET,您确实应该在使用命令和连接时创建、使用和处理它们。性能方面,我从来没有改变过这个系统......而且我还没有真正听说过很多其他的系统。

        此外,正如其他人在您的代码示例中提到的那样,实际执行所需的连接无论如何都会丢失。

        【讨论】:

          【解决方案4】:

          你为什么要缓存命令?创建命令的开销微乎其微——您只需新建几个对象并设置一些属性。我从来没有看到这是一个瓶颈..

          您想要缓存命令的结果,因为实际上执行命令是(相对)昂贵的。而且,一般来说,您希望将共享缓存视为只读,这样您就不必担心锁定和同步访问。缓存结果可以实现这一点。

          【讨论】:

            【解决方案5】:

            我应该问如何在 ASP.NET 缓存中锁定项目,而不是说我打算放入缓存中的内容。

            lock(Cache)
              {
                // do something with cache that otherwise wouldn't be threadsafe
              }
            

            参考:http://www.codeguru.com/csharp/.net/net_asp/article.php/c5363

            【讨论】:

            • 恕我直言,比链接文章中更好的解决方案是将线程安全对象放入缓存中:这可以是非线程安全对象的线程安全包装器。跨度>
            【解决方案6】:

            缓存您的结果,并且仅在结果缓存为空时创建连接(和命令):

            伪代码:

            result = getResultFromCache(CacheKey)
            if (result == null)
            {
                 result = getResultFromDB();
                 InsertIntoCache(result,cacheKey);
            }
            
            return result;
            

            【讨论】:

              猜你喜欢
              • 2012-04-05
              • 1970-01-01
              • 2015-12-22
              • 2019-02-20
              • 2014-04-18
              • 2012-11-08
              • 2011-10-22
              • 2011-05-02
              • 1970-01-01
              相关资源
              最近更新 更多