我有一个Module类,一个User,一个UserModule和一个UserModuleLevel类。如何更有效地填充用户细节的集合
_module_objects是模块的静态ObservableCollection,在程序启动时创建,其中大约有10个。例如用户管理,客户服务等。
用户,你可能会猜到的是用户的详细信息:ID,名称等填入数据库查询。
使用UserModules,我不保留模块信息在数据库中,只是模块级别,这只是模块的安全级别。这保存在数据库中:User_ID,Module_ID,ModuleLevel,ModuleLevelAccess。
我想要做的是以最快的方式填充用户的ObservableCollection。我有大约120,000个用户,通常这些用户只能访问10个模块中的2个或3个。
下面是我到目前为止所尝试的,但是周围有星号的部分是瓶颈,因为它正在经历每个用户的每个模块。
希望得到一些建议,以加快速度。
public class UserRepository
{
ObservableCollection<User> m_users = new ObservableCollection<User>();
public UserRepository(){}
public void LoadUsers()
{
var users = SelectUsers();
foreach (var u in users)
{
m_users.Add(u);
}
}
public IEnumerable<User> SelectUsers()
{
var userModulesLookup = GetUserModules();
var userModuleLevelsLookup = GetUserModuleLevels().ToLookup(x => Tuple.Create(x.User_ID, x.Module_ID));
clsDAL.SQLDBAccess db = new clsDAL.SQLDBAccess("DB_USERS");
db.setCommandText("SELECT * FROM USERS");
using (var reader = db.ExecuteReader())
{
while (reader.Read())
{
var user = new User();
var userId = NullSafeGetter.GetValueOrDefault<int>(reader, "USER_ID");
user.User_ID = userId;
user.Username = NullSafeGetter.GetValueOrDefault<string>(reader, "USERNAME");
user.Name = NullSafeGetter.GetValueOrDefault<string>(reader, "NAME");
user.Job_Title = NullSafeGetter.GetValueOrDefault<string>(reader, "JOB_TITLE");
user.Department = NullSafeGetter.GetValueOrDefault<string>(reader, "DEPARTMENT");
user.Company = NullSafeGetter.GetValueOrDefault<string>(reader, "COMPANY");
user.Phone_Office = NullSafeGetter.GetValueOrDefault<string>(reader, "PHONE_OFFICE");
user.Phone_Mobile = NullSafeGetter.GetValueOrDefault<string>(reader, "PHONE_MOBILE");
user.Email = NullSafeGetter.GetValueOrDefault<string>(reader, "EMAIL");
user.UserModules = new ObservableCollection<UserModule>(userModulesLookup);
//**************** BOTTLENECK **********************************
foreach (var mod in user.UserModules)
{
mod.UserModuleLevels = new ObservableCollection<UserModuleLevel>(userModuleLevelsLookup[Tuple.Create(userId, mod.Module.Module_ID)]);
}
//**************************************************************
yield return user;
}
}
}
private static IEnumerable<Users.UserModule> GetUserModules()
{
foreach (Module m in ModuleKey._module_objects)
{
//Set a reference in the UserModule to the original static module.
var user_module = new Users.UserModule(m);
yield return user_module;
}
}
private static IEnumerable<Users.UserModuleLevel> GetUserModuleLevels()
{
clsDAL.SQLDBAccess db_user_module_levels = new clsDAL.SQLDBAccess("DB_USERS");
db_user_module_levels.setCommandText(@"SELECT * FROM USER_MODULE_SECURITY");
using (var reader = db_user_module_levels.ExecuteReader())
{
while (reader.Read())
{
int u_id = NullSafeGetter.GetValueOrDefault<int>(reader, "USER_ID");
int m_id = NullSafeGetter.GetValueOrDefault<int>(reader, "MODULE_ID");
int ml_id = NullSafeGetter.GetValueOrDefault<int>(reader, "MODULE_LEVEL_ID");
int mla = NullSafeGetter.GetValueOrDefault<int>(reader, "MODULE_LEVEL_ACCESS");
yield return new Users.UserModuleLevel(u_id, m_id, ml_id, mla);
}
}
}
}
最后,我会把用户与模块安全DataGrid中显示,绿色显示的按钮有某种类型的上网本模块的,点击它会弹出实际的安全设置。
你是怎么定义你的USER_MODULE_SECURITY的?如果您只为每个用户存储授予的模块安全级别,那么当您使用'USER_MODULE_SECURITY'加入'USERS'时,您可以只使用一个表? – Bolu
[this](http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization)可能会有所帮助,但需要您的努力,因为这是一篇长篇文章。 – kennyzx
听起来像你可以很容易地在单个查询中获取这些信息,而不是查询这两个表,并在应用程序代码中使用剪刀/粘合方法(在将事物粘合在一起时SQL可以快几个数量级)。这需要多长时间才能完成 - 您为什么需要同时处理所有120,000个用户?怎么样寻呼或部分负载策略? – Charleh