zer*_*kms 7 singleton linq-to-sql
当linq2sql使用(在asp.net mvc应用程序中)时,首选的做法是:为DataContextlike 创建"singleton" :
partial class db
{
static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource());
public static db GetInstance()
{
return _db;
}
}
Run Code Online (Sandbox Code Playgroud)
或者在需要时检索新实例using:
using (db _db = new db())
{
...
}
Run Code Online (Sandbox Code Playgroud)
使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
我有这种方法.由于它返回IQueryable - 我可以继续编写查询而不执行它,所以这里只是懒惰的结果返回.
如果我重写相同的代码using- 我无法返回IQueryable(因为db将被丢弃,IQueryable也会丢失),我会将其更改为List.现在这个方法将返回"巨大的"List,我将从中过滤前一个函数的数据.
我希望我描述得足够详细.
Linq to Sql数据上下文不是线程安全的,只应在单个线程的上下文中使用.使用单例模式不仅违反了标准的linq2sql实践,而且如果您的应用程序遇到任何严重的负载,也会导致严重的问题.
编辑:
为了响应您对using块的限制,请尝试将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;
}
Run Code Online (Sandbox Code Playgroud)
这将允许您从任何地方在使用块内调用您的方法:
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();
}
Run Code Online (Sandbox Code Playgroud)
编辑2
响应您关于为数据上下文的每个实例打开与sql server的另一个连接的注释.创建datacontext不会打开与sql server的连接,但每个实际操作都会.无论您是创建1个还是4个datacontexts,如果您在数据库上执行4个操作,将打开4个sqlconnections.但是,请在.NET中使用SQL Server连接池的头脑,所以每个操作不需要建立一个全新的SqlConnection的,但只有一个现有的连接池中的检索和连接的重新开放