C# 如何更有效地填充用户详细信息集合

C# 如何更有效地填充用户详细信息集合,c#,wpf,C#,Wpf,我有一个模块类、一个用户、一个UserModule和一个UserModuleLevel类 _模块_对象是模块的静态可观察集合,在程序启动时创建,大约有10个模块。e、 g.用户管理、客户服务等 您可能猜到的用户是用户详细信息:ID、名称等,由db查询填充 对于UserModules,我不在数据库中保存模块信息,只保留模块级别,这只是模块安全级别。这在数据库中保存为:用户ID、模块ID、模块级别、模块级别访问 我想做的是以最快的方式填充一个可观察的用户集合。我有大约120000个用户,通常这些用户

我有一个模块类、一个用户、一个UserModule和一个UserModuleLevel类

_模块_对象是模块的静态可观察集合,在程序启动时创建,大约有10个模块。e、 g.用户管理、客户服务等

您可能猜到的用户是用户详细信息:ID、名称等,由db查询填充

对于UserModules,我不在数据库中保存模块信息,只保留模块级别,这只是模块安全级别。这在数据库中保存为:用户ID、模块ID、模块级别、模块级别访问

我想做的是以最快的方式填充一个可观察的用户集合。我有大约120000个用户,通常这些用户只能访问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);
            }
        }
    }
}
公共类用户存储库
{
ObservableCollection m_users=新的ObservableCollection();
公共用户存储库(){}
公共void LoadUsers()
{
var users=SelectUsers();
foreach(用户中的var u)
{
m_用户。添加(u);
}
}
公共IEnumerable SelectUsers()
{
var userModulesLookup=GetUserModules();
var userModuleLevelsLookup=GetUserModuleLevels().ToLookup(x=>Tuple.Create(x.User\u ID,x.Module\u ID));
clsDAL.SQLDBAccess db=新的clsDAL.SQLDBAccess(“db_用户”);
db.setCommandText(“从用户中选择*);
使用(var reader=db.ExecuteReader())
{
while(reader.Read())
{
var user=新用户();
var userId=NullSafeGetter.GetValueOrDefault(读卡器,“用户ID”);
user.user_ID=用户ID;
user.Username=NullSafeGetter.GetValueOrDefault(读卡器,“用户名”);
user.Name=NullSafeGetter.GetValueOrDefault(读卡器,“名称”);
user.Job_Title=NullSafeGetter.GetValueOrDefault(读取器,“Job_Title”);
user.Department=NullSafeGetter.GetValueOrDefault(读卡器,“Department”);
user.Company=NullSafeGetter.GetValueOrDefault(读卡器,“公司”);
user.Phone\u Office=NullSafeGetter.GetValueOrDefault(读卡器,“Phone\u Office”);
user.Phone\u Mobile=NullSafeGetter.GetValueOrDefault(读卡器,“Phone\u Mobile”);
user.Email=NullSafeGetter.GetValueOrDefault(读卡器,“电子邮件”);
user.UserModules=新的ObservableCollection(userModulesLookup);
//****************瓶颈**********************************
foreach(user.UserModules中的var mod)
{
mod.UserModuleLevels=新的ObservableCollection(userModuleLevelsLookup[Tuple.Create(userId,mod.Module.Module\u ID)];
}
//**************************************************************
用户收益率;
}
}
}
私有静态IEnumerable GetUserModules()
{
foreach(模块key.\u模块\u对象中的模块m)
{
//在UserModule中设置对原始静态模块的引用。
var user_module=新用户。UserModule(m);
收益返回用户单元模块;
}
}
私有静态IEnumerable GetUserModuleLevel()
{
clsDAL.SQLDBAccess db_user_module_levels=新的clsDAL.SQLDBAccess(“db_USERS”);
db_user_module_levels.setCommandText(@“从用户_module_安全性中选择*);
使用(var reader=db\u user\u module\u levels.ExecuteReader())
{
while(reader.Read())
{
int u_id=NullSafeGetter.GetValueOrDefault(读卡器,“用户id”);
int m_id=NullSafeGetter.GetValueOrDefault(读卡器,“模块id”);
int ml_id=NullSafeGetter.GetValueOrDefault(读卡器,“模块级别id”);
int mla=NullSafeGetter.GetValueOrDefault(读卡器,“模块级访问”);
返回新的Users.UserModuleLevel(u\u id,m\u id,ml\u id,mla);
}
}
}
}

最后,我将把用户放入显示模块安全性的数据网格中,绿色按钮显示有某种类型的访问此模块的权限,单击它将显示实际的安全设置。

为了提高性能,您可以做以下几件事:

  • 更改数据访问代码以在SQL中执行联接,从而将数据作为单个结果集获取

    SQL在返回关系数据的结果集方面往往比C#在事后将数据粘在一起要快得多。这是因为它被优化来实现这一点,您应该充分利用这一点

  • >P>你可能应该考虑分页结果-任何一个说他们需要所有120000个结果的用户都应该被拍打在头顶上,并有一个大鳟鱼。分页结果将限制您需要在应用程序中执行的处理量

执行上述操作可能会让人望而生畏,因为您需要修改应用程序以包含分页功能-通常第三方控件(如网格等)内置了一些分页机制,而现在大多数ORM软件都有某种分页支持,可以将您的C#代码转换为所选RDBMS的正确方言

一个很好的例子(我最近一直在使用)是ServiceStack OrmLite

我相信,只要您使用的是遗留的V3版本(这是非常好的…),它是免费的,我在GitHub上看到了一些目前维护的版本()

有一个小的学习曲线,但没有什么例子/文档不能告诉你的

下面是我用来在服务层中分页查询的扩展方法:

public static SqlExpressionVisitor<T> PageByRequest<T>(this SqlExpressionVisitor<T> expr, PagedRequest request)
{
    return expr.Limit((request.PageNumber - 1) * request.PageSize, request.PageSize);
}
该方法被转换为T-SQL,并根据
[Alias("Customers")]
public class Customer : IHasId<string>
{
    [Alias("AccountCode")]
    public string Id { get; set; }

    public string CustomerName { get; set; }
    // ... a load of other fields
}
SELECT <A big list of Fields> FROM 
(SELECT ROW_NUMBER() OVER (ORDER BY AccountCode) As RowNum, * FROM "Customers") 
AS RowConstrainedResult 
WHERE RowNum > 40 AND RowNum <= 50