我有一個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