linq2sql使用时(在asp.net mvc应用程序中)的首选做法是:为DataContext
创建“singleton”,如:
partial class db
{
static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource());
public static db GetInstance()
{
return _db;
}
}
或在using
内需要时检索新实例:
using (db _db = new db())
{
...
}
using
的使用会给代码带来一些限制。所以我更喜欢使用单身之一。是不是很奇怪?
UPD :
解释为什么我使用单身:
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;
}
}
我有这种方法。由于它返回IQueryable - 我可以继续编写查询而不执行它,所以这里只是懒惰的结果返回
如果我用using
重写相同的代码 - 我无法返回IQueryable(因为db将被丢弃并且IQueryable也会丢失),我会将其更改为List。现在这个方法将返回“巨大的”List,我将从中过滤前一个函数的数据。
我希望我描述得足够详细。
答案 0 :(得分:5)
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;
}
这将允许您从任何地方在使用块内调用您的方法:
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();
}
编辑2
响应您关于为数据上下文的每个实例打开与sql server的另一个连接的注释。创建datacontext不会打开与sql server的连接,但每个实际操作都会。无论您是创建1个还是4个datacontexts,如果您在数据库上执行4个操作,将打开4个sqlconnections。但是,请记住,.NET使用sql server连接池,因此每个操作不需要创建全新的SqlConnection,而只需要从连接池中检索现有的连接池并重新打开连接
答案 1 :(得分:2)
Linq to SQL希望您为每个操作创建一个上下文。实际上,只能为执行第一个查询设置数据加载选项,因此如果要加载提示,则必须这样做。但是,当您拥有3层体系结构时,您将遇到以下问题:来自一个datacontext的对象无法真正处理来自不同上下文的对象。
解决这个问题真是太痛苦了,所以我们只针对Web服务的请求和Windows服务等的线程本地方法做了上下文。
答案 2 :(得分:0)
您可能希望管理上下文的生命周期,将其范围限定为单个Web请求,并且在该Web请求周期的生命周期内只有一个上下文。
Google搜索“web scoped objectcontext”或“objectcontext lifetime”(或l2s的datacontext)。
在MVC2中,您可以将上下文管理代码放在基本控制器类中。