У меня есть класс модуля, Пользователь, UserModule и класс UserModuleLevel.Как более эффективно заполнять коллекцию деталей пользователя
_module_objects является статическим ObservableCollection модулей и создается при запуске программы, из них около 10. например Управление пользователями, Обслуживание клиентов и т. Д.
Пользователь, как вы можете догадаться, это данные пользователя: ID, имя и т. Д. Заполнено из запроса db.
С помощью UserModules я не сохраняю информацию о модуле в db, только уровень модуля, который является только уровнем безопасности модуля. это хранится в db как: User_ID, Module_ID, ModuleLevel, ModuleLevelAccess.
Что я пытаюсь сделать, это заполнить ObservableCollection пользователей самым быстрым способом. У меня около 120 000 пользователей, обычно эти пользователи имеют доступ только к 2 или 3 из 10 модулей.
Ниже приведено то, что я пробовал до сих пор, однако кусок со звездочками вокруг него - это горлышко бутылки, потому что он проходит через каждый модуль каждого пользователя.
Надеясь на некоторые советы, чтобы ускорить процесс.
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'? если вы сохраняете только уровни безопасности модулей для каждого пользователя, тогда, когда вы присоединяетесь к 'USERS' с' USER_MODULE_SECURITY', вы можете просто работать с одной таблицей? – Bolu
[this] (http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization) может помочь, но требует ваших усилий, потому что это длинная статья. – kennyzx
Похоже, что вы можете легко получить эту информацию в одном запросе, а не запрашивать эти две таблицы и использовать подход scissors/glue в коде приложения (SQL может быть на порядок быстрее при склеивании вещей). Как долго это происходит, чтобы пройти через список - и почему вам нужно обрабатывать всех 120 000 пользователей одновременно? Как насчет стратегии поискового вызова или частичной загрузки? – Charleh