具有Linq to Entities性能的实体框架

时间:2010-05-14 18:01:08

标签: c# entity-framework linq-to-entities

如果我有这样的静态方法

    private static bool TicArticleExists(string supplierIdent)
    {
        using (TicDatabaseEntities db = new TicDatabaseEntities())
        {
            if((from a in db.Articles where a.SupplierArticleID.Equals(supplierIdent) select a).Count() > 0)
                return true;                
        }
        return false;
    }

并在foreach循环中的各个地方使用此方法,或者只是简单地调用它多次,是否每次都创建并打开新连接?

  1. 如果是这样,我该怎样解决这个问题?我应该在某处缓存结果,比如在这种情况下,我会将整个分类表缓存在内存缓存中吗?然后对这个缓存的对象进行查询?
  2. 或者我应该将TicDatabaseEntities变量设为静态并在类级别初始化它吗?
  3. 如果我的类只包含静态方法,那么它应该是静态的吗?因为现在不是..
  4. 另外我注意到如果我返回result.First()而不是FirstOrDefault()并且查询找不到匹配项,它将发出异常(使用FirstOrDefault()没有异常,它返回null)
  5. 感谢您的澄清。

4 个答案:

答案 0 :(得分:1)

  • 由于连接缓存,新连接非常昂贵。基本上,它抓住了一个已经打开的连接(我想它们会保持打开2分钟以便重复使用)。

  • 尽管如此,缓存可能会更好。我真的不喜欢“firstordefault”。想想你是否可以在一个陈述中更多地接受更多信息,然后从那里开始工作。

对于其他人,我不能说什么 - 太多取决于你在逻辑上做了什么。什么是TicDatabaseEntities?可以缓存吗?多久?与(3)相同 - 我们不知道,因为我们不知道那里还有什么。

如果这只是获取一些查找字符串供以后使用,我会说......

  • 从classI,class II,class III中构建一个密钥
  • 加载所有分类(我假设只有几百个)
  • 将它们放入静态/缓存字典中,假设它们通常不会更改(我想我在这里有这个想法 - 这是一个财务流程数据库吗?)

没有商业知识,这无法回答。

4:是的,这是记录在案的。 First给出第一个或异常,FirstOrDefault默认为默认值(空结构初始化为0,null为类)。

答案 1 :(得分:0)

感谢Dan和TomTom,我想出了这个。如果你看到任何东西或订单,请你评论一下吗?

    public static IEnumerable<Article> TicArticles
    {
        get
        {
            ObjectCache cache = MemoryCache.Default;
            if (cache["TicArticles"] == null)
            {
                CacheItemPolicy policy = new CacheItemPolicy();
                using(TicDatabaseEntities db = new TicDatabaseEntities())
                {
                    IEnumerable<Article> articles = (from a in db.Articles select a).ToList();
                    cache.Set("TicArticles", articles, policy);
                }
            }

            return (IEnumerable<Article>)MemoryCache.Default["TicArticles"];
        }
    }


    private static bool TicArticleExists(string supplierIdent)
    {
        if (TicArticles.Count(p => p.SupplierArticleID.Equals(supplierIdent)) > 0)
            return true;
        return false;
    }

如果可以,我将使我的所有方法都遵循这种模式。

答案 2 :(得分:0)

  

每次创建和打开新连接吗?

没有。连接被缓存。

  

我应该将结果缓存到某个地方

没有。不要缓存整个表。

  

我应该将TicDatabaseEntities变量设为静态并在类级别初始化它吗?

没有。不要将DataContext实例保留得比UnitOfWork更长。

  

如果我的类只包含静态方法,那么它应该是静态的吗?

当然......这样做会阻止任何人创建无用的类实例。

  

另外我注意到如果我返回result.First()而不是FirstOrDefault()并且查询找不到匹配项,它将发出异常

这是First的行为。因此 - 我通常将First的使用限制为IGroupings或先前使用.Any()检查的集合。


我将现有方法重写为:

using (TicDatabaseEntities db = new TicDatabaseEntities()) 
{
  bool result = db.Articles
    .Any(a => a.supplierArticleID.Equals(supplierIdent));

  return result;
}

如果你在循环中调用方法,我会重写为:

private static Dictionary<string, bool> TicArticleExists
  (List<string> supplierIdents)   
{
  using (TicDatabaseEntities db = new TicDatabaseEntities())   
  {   
    HashSet<string> queryResult = new HashSet(db.Articles
      .Where(a => supplierIdents.Contains(a.supplierArticleID))
      .Select(a => a.supplierArticleID));

    Dictionary<string, bool> result = supplierIdents
      .ToDictionary(s => s, s => queryResult.Contains(s));

    return result;
  }
}

答案 3 :(得分:0)

我正在尝试找到我读过这篇文章的文章,但我认为最好这样做(如果你只是在寻找一个计数):

from a in db.Articles where a.SupplierArticleID.Equals(supplierIdent) select 1

另外,使用Any代替Count&gt; 0

当我可以引用来源时会更新。