Linq to sql linq2sql:单例还是使用,最佳实践

Linq to sql linq2sql:单例还是使用,最佳实践,linq-to-sql,singleton,Linq To Sql,Singleton,linq2sql使用(在asp.net mvc应用程序中)时,首选的做法是:为DataContext创建“单例”,如: partial class db { static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource()); public static db GetInstance() {

linq2sql使用(在asp.net mvc应用程序中)时,首选的做法是:为
DataContext
创建“单例”,如:

partial class db
{
    static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource());

    public static db GetInstance()
    {
        return _db;
    }
}
或者在
中需要时使用
检索新实例:

using (db _db = new db())
{
    ...
}
使用
会给代码带来一些限制。所以我更喜欢使用单例。这是奇怪的做法吗

UPD
解释我使用singleton的原因:

public class UserGroupRepository
{
    public static IQueryable<Group> RolesFor(string username)
    {
        User user = UserRepository.WithUsername(username);

        return from g in db.GetInstance().Groups
                join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId
                where ug.UserId == user.Id
                select g;
    }
}
public类UserGroupRepository
{
公共静态IQueryable角色(字符串用户名)
{
User=UserRepository.WithUsername(用户名);
从db.GetInstance()组中的g返回
在db.GetInstance()中加入ug。g.Id上的UsersGroups等于ug.GroupId
其中ug.UserId==user.Id
选择g;
}
}
我有这个方法。由于它返回IQueryable—我可以继续编写查询而不执行它,所以这里只返回惰性结果。
如果我用
使用
重写相同的代码,我将无法返回IQueryable(因为db将被释放,IQueryable也将丢失),我会将其更改为List。现在这个方法将返回“巨大的”列表,我将从中过滤上一个函数的数据


我希望我的描述足够详细。

Linq to Sql数据上下文不是线程安全的,只能在单个线程的上下文中使用。使用单例模式不仅与标准linq2sql实践相反,而且如果您的应用程序承受任何类型的严重负载,都会导致严重的问题

编辑:

针对您在使用块方面的限制,尝试将RolesFor方法作为扩展方法实现:

public static IQueryable<Group> GetUserRoles(this Database db, string username)
{
        return from g in db.GetInstance().Groups
                join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId
                where ug.UserId == user.Id
                select g;
}
public静态IQueryable GetUserRoles(此数据库数据库数据库,字符串用户名)
{
从db.GetInstance()组中的g返回
在db.GetInstance()中加入ug。g.Id上的UsersGroups等于ug.GroupId
其中ug.UserId==user.Id
选择g;
}
这将允许您在using块内的任何位置调用您的方法:

using(Database db = createContext())
{
     IQueryable<Group> queryable = db.GetUserRoles("MyUsername");
     // from here on you can query the queryable object
     var groups = (from g in queryable
                   where g.Name == "MyRole"
                   select g).ToList();
}
使用(数据库db=createContext())
{
IQueryable queryable=db.GetUserRoles(“MyUsername”);
//从这里开始,您可以查询可查询对象
变量组=(来自查询表中的g)
其中g.Name==“MyRole”
选择g.ToList();
}
编辑2


回应您关于为数据上下文的每个实例打开与sql server的另一个连接的评论。创建datacontext不会打开到sql server的连接,但每个实际操作都会打开连接。无论创建1个还是4个DataContext,如果在数据库上执行4个操作,将打开4个sqlconnections。但是,请记住,.NET使用sql server连接池,因此每个操作都不需要创建全新的sql连接,但是,只有从连接池中检索现有的上下文并重新打开连接,您可能需要管理上下文的生存期,将其范围限定为单个web请求,并且在该web请求周期的生存期内只有一个上下文

谷歌搜索“web范围的objectcontext”或“objectcontext生存期”(或l2s的datacontext)

e、 g


在MVC2中,您可以将上下文管理代码放在基本控制器类中。

Linq to SQL希望您为每个操作创建一个上下文。事实上,只能为执行第一个查询设置数据加载选项,因此,如果要执行加载提示,必须这样做。然而,当您有一个三层体系结构时,您将遇到一个问题,即来自一个datacontext的对象不能真正与来自不同上下文的对象一起工作


解决这个问题真的很痛苦,所以我们只是针对web内容的每个请求做了一个上下文,针对Windows服务等做了一个线程本地方法。

出于好奇,使用“using”会产生什么限制?也许有一个很好的绕过它们的方法…@LorenVS:我打赌“限制”是因为我是新手,所以我相信也有一个优雅的解决方案,使用
,-)在我的帖子中添加了关于您的update@zerkms,从您对我和其他帖子的回复来看,在我看来,您似乎认为Linq2Sql datacontext是一个昂贵的对象。。。事实并非如此,数据上下文(通常)是可以快速创建和处理的廉价对象。与检索数据的实际过程相比,数据上下文对象的创建将非常简单是的,感谢您的解释:-)我真的认为datacontext在创建新的数据库连接方面有开销(这是昂贵的)。因此,如果它是错误的-那么在singleton中就不需要了;-)@洛伦夫斯:我把UPD加在原来的问题上,解释我为什么问这个问题。@zerkms,请澄清你的意思,在什么方面它在概念上是错误的,你说浪费db是什么意思class@zerkms,您只需将扩展方法转换为普通方法,并将Db对象作为参数,然后将该方法放入您的usergrouprepository…@zerkms,如果您非常担心功能的显示方式,那么您唯一正确的选择是创建一个实现IDisposable和IQueryable的类,并包含Db类的实例。。。这样的类将在内部创建适当的IQueryable,并公开IQueryable的方法。然后,您可以在using语句中使用该类(您的类的dispose方法将调用db对象的dispose方法,这是完全安全的)@zerkms,不是您的单例模式是线程安全的。您的单例模式将很好地工作。这里的问题是,实际的DataContext对象不是线程安全的。您的单例模式确保只创建1个DataContext,而不考虑线程条件(它所做的)