23

有人可以就性能、内存使用、编码的便利性、正确的做法等因素在使用语句中包装 DataContext 或不在 LINQ-SQL 中包装 DataContext 之间的优缺点发表意见吗?

更新在一个特定的应用程序中,我体验到,如果没有将 DataContext 包装在 using 块中,由于没有为 GC 释放活动对象,内存使用量会不断增加。如在下面的示例中,如果我持有对 q 对象列表的引用并访问 q 的实体,我将创建一个不为 GC 释放的对象图。

使用 DataContext

    using (DBDataContext db = new DBDataContext())
    {
        var q = 
            from x in db.Tables
            where x.Id == someId
            select x;

        return q.toList();
    }

DataContext 不使用并保持活动状态

  DBDataContext db = new DBDataContext()
  var q = 
        from x in db.Tables
        where x.Id == someId
        select x;

    return q.toList(); 

谢谢。

4

5 回答 5

12

相对于其他事物,创建 DataContext 的成本可能很高。但是,如果您完成了它并希望尽快关闭连接,这将执行此操作,同时从上下文中释放任何缓存的结果。请记住,无论如何您都是在创建它,在这种情况下,您只是让垃圾收集器知道还有更多免费的东西要摆脱。

DataContext 是一个短期使用对象,使用它,完成工作单元,退出......这正是您使用 using 所做的事情。

所以优点:

  • 更快的关闭连接
  • 从 dispose 中释放内存(内容中的缓存对象)

缺点 - 更多代码?但这不应该是一种威慑,你在using这里使用得当。

看看这里的微软答案: http ://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe

如果您需要使用using/的简短版本.Dispose()

简短的回答;不,你不必,但你应该...

于 2010-02-18T21:56:33.267 回答
5

嗯,这是一个IDisposable,所以我想这不是一个坏主意。MSFT 的人说他们使 DataContexts 尽可能轻量级,这样你就可以不顾一切地创建它们,所以你可能不会获得太多......

于 2010-02-18T21:57:00.563 回答
5
  1. 第一次 DataContext 将从数据库中获取对象。
  2. 下次您触发查询以获取相同的对象(相同的参数)。:您将在探查器中看到查询,但 DataContext 中的对象不会被 DB 中的新对象替换!

更不用说每个 DataContext 背后都是您从 DB 询问的所有对象的身份映射(您不想保留它)。

DataContext 的整个想法是Unit Of Work with Optimistic Concurrency。将其用于短交易(仅提交一次)并处置。

不要忘记 dispose 的最好方法是使用 ()。

于 2010-03-19T19:17:16.000 回答
3

我取决于您的数据层的复杂性。如果每个调用都是一个简单的单个查询,那么每个调用都可以包含在您问题中的 Using like 中,这很好。

另一方面,如果您的数据层可以预期来自业务层的多个顺序调用,那么您最终会为每个更大的调用序列重复创建/处理 DataContext。不理想。

我所做的是将我的数据层对象创建为 IDisposible。创建时,会创建 DataContext(或者实际上,一旦对方法进行第一次调用),当数据层对象释放时,它会关闭并释放 DataContext。

这是它的样子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace PersonnelDL
{
    public class PersonnelData : IDisposable
    {
        #region DataContext management
        /// <summary>
        /// Create common datacontext for all data routines to the DB
        /// </summary>
        private PersonnelDBDataContext _data = null;
        private PersonnelDBDataContext Data
        {
            get
            {
                if (_data == null)
                {
                    _data = new PersonnelDBDataContext(ConfigurationManager.ConnectionStrings["PersonnelDB"].ToString());
                    _data.DeferredLoadingEnabled = false; // no lazy loading
                    //var dlo = new DataLoadOptions(); // dataload options go here
                }
                return _data;
            }
        }

        /// <summary>
        /// close out data context
        /// </summary>
        public void Dispose()
        {
            if (_data != null)
                _data.Dispose();
        }
        #endregion

        #region DL methods
        public Person GetPersonByID(string userid)
        {
            return Data.Persons.FirstOrDefault(p => p.UserID.ToUpper().Equals(userid.ToUpper()));
        }

        public List<Person> GetPersonsByIDlist(List<string> useridlist)
        {
            var ulist = useridlist.Select(u => u.ToUpper().Trim()).ToList();
            return Data.Persons.Where(p => ulist.Contains(p.UserID.ToUpper())).ToList();
        }

        // more methods...
        #endregion
    }
}
于 2010-02-19T14:50:36.647 回答
1

在一个特定的应用程序中,我体验到,在不包装DataContextinusing块的情况下,由于没有为 GC 释放活动对象,内存使用量不断增加。如在下面的示例中,如果我持有对 的List<Table>对象和访问实体的引用q,我将创建一个不为 GC 释放的对象图。

DBDataContext db = new DBDataContext()
var qs = 
    from x in db.Tables
    where x.Id == someId
    select x;

return qs.toList();

foreach(q in qs)
{
    process(q);
    // cannot dispose datacontext here as the 2nd iteration 
    // will throw datacontext already disposed exception 
    // while accessing the entity of q in process() function
    //db.Dispose();
}

process(Table q)
{
    // access entity of q which uses deferred execution
    // if datacontext is already disposed, then datacontext 
    // already disposed exception is thrown
}

鉴于此示例,我无法处理 datacontext,因为列表变量 ** 中的所有实例共享相同的 datacontextTableqs。之后Dispose(),访问中的实体process(Table q)会引发 datacontext 已经处理的异常。

对我来说,丑陋的 kluge 是在 foreach 循环之后删除 q 对象的所有实体引用。更好的方法当然是使用using语句。

就我的经验而言,我会说使用该using声明。

于 2010-03-06T16:19:02.807 回答