GridView展示Active Directory用户报“该行已属于此表”错误如何解决
错误根因
- 核心问题是
DataRow dr = dt.NewRow();的初始化逻辑放在了foreach循环外部,全程复用同一个DataRow实例:第一次将dr添加到DataTable的行集合后,该实例就已经和当前DataTable绑定,后续循环再次尝试添加同一个实例时,就会触发This row already belongs to this table报错。
修复方案
将DataRow的创建逻辑移动到foreach循环内部,每次循环生成全新的行对象,同时补充可空类型判空、资源释放的优化逻辑,修复后代码如下:
DirectoryEntry objDirEntry = new DirectoryEntry(strADPath, strUsername, strPassword); PrincipalContext ctx = new PrincipalContext(ContextType.Domain, strADPath, strUsername, strPassword); UserPrincipal usr = new UserPrincipal(ctx); // 用using包裹自动释放查询资源 using (PrincipalSearcher ps = new PrincipalSearcher(usr)) { PrincipalSearchResult<Principal> results = ps.FindAll(); DataTable dt = new DataTable(); dt.Columns.Add("First Name"); dt.Columns.Add("Last Name"); dt.Columns.Add("Last Logon"); dt.Columns.Add("Last Password Reset"); foreach (UserPrincipal u in results) { // 每次循环创建新的行对象 DataRow dr = dt.NewRow(); dr["First Name"] = u.DisplayName ?? string.Empty; dr["Last Name"] = u.SamAccountName ?? string.Empty; // 可空类型判空,避免空引用异常 dr["Last Logon"] = u.LastLogon?.ToString() ?? "无记录"; dr["Last Password Reset"] = u.LastPasswordSet?.ToString() ?? "无记录"; dt.Rows.Add(dr); } grdViewAllADSUsers.DataSource = dt; grdViewAllADSUsers.DataBind(); } catch (Exception ex) { error.Text = ex.Message; }
额外注意事项
PrincipalSearcher实现了IDisposable接口,使用using包裹可以自动释放非托管AD查询资源,避免内存泄漏。- UserPrincipal的
LastLogon、LastPasswordSet、DisplayName等属性均为可空类型,直接调用方法或赋值可能触发空引用异常,建议统一加空值兼容处理。
内容的提问来源于stack exchange,提问作者Allrounder
相关产品推荐
相关产品推荐

