UserPrincipal.Save()导致ObjectDisposedException [英] UserPrincipal.Save() causes an ObjectDisposedException

查看:74
本文介绍了UserPrincipal.Save()导致ObjectDisposedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一下我拥有的Active Directory服务中的以下代码。在 Rename()方法中,它总是抛出 ObjectDisposedException 无法访问已处置的对象。对象名:'DirectoryEntry'。

Consider the following pieces of code from an Active Directory service I have. In the Rename() method it always throws an ObjectDisposedException, "Cannot access a disposed object. Object name: 'DirectoryEntry'."

这曾经很好用,但是我也有一个 Add()方法和两者的95%代码相同。因此,我选择了 SetIdentity()方法,将主体和属性字典传递给该方法,然后从那里开始。 Add()方法有效,但这是因为尚无底层对象可操作。 Rename()方法失败,因为有一个方法。

This used to work fine, but I also have an Add() method and the two were 95% identical code. So, I opted for the SetIdentity() method to which I would pass the principal and the properties dictionary and go from there. The Add() method works, but that's because there's no underlying object to manipulate yet. The Rename() method fails because there is one.

我知道,如果我把代码从 SetIdentity()返回到 Rename(),它可以正常工作,但我不想这样做。

I know that if I put the code from SetIdentity() back into Rename() it will work just fine, but I don't want to do that.

我尝试将 using 子句包装在 Rename()在 try / catch 块中,但是它什么也没做。我尝试通过 ref 传递校长和字典,但这也无济于事。我试过检查 DirectoryEntry 是否为空并且没有帮助。

I've tried wrapping the using clause in Rename() in a try/catch block, but it didn't do anything. I've tried passing the principal and dictionary by ref, but that also didn't help. I've tried checking if the DirectoryEntry is null and it didn't help.

所以,我猜测它不是失败的 using 子句中的代码。我还应该寻找什么?

So, I'm guessing it can't be the code inside the using clause that's failing. What else should I look for?

使用Visual Studio进行调试时,我可以将鼠标悬停在该对象上,并且该对象在那里并带有属性和值,因此我不知道该在哪里我应该在看...

When debugging with Visual Studio I can hover over the object and it's there and complete with properties and values, so I don't know where I'm supposed be looking...

public override void Rename(
    UserPrincipal principal,
    IDictionary<string, object> properties) {
    if (principal != null) {
        this.SetIdentity(ref principal, ref properties);

        using (DirectoryEntry entry = (principal.GetUnderlyingObject() as DirectoryEntry)) {
            entry.Rename(newName: String.Format("CN={0}", principal.DisplayName));
            entry.CommitChanges();
        };

        principal.Save(); // this is where ASP.NET runtime points to when failed
    };
} // this is where Visual Studio points to when debugging

internal void SetIdentity(
    ref UserPrincipal principal,
    ref IDictionary<string, object> properties) {
    object obj = null;
    string displayName = string.Empty;
    string givenName = string.Empty;
    string middleName = string.Empty;
    string samAccountName = string.Empty;
    string surname = string.Empty;

    if (properties.TryGetValue("GivenName", out obj)) {
        givenName = (string)properties["GivenName"];
    };

    if (properties.TryGetValue("MiddleName", out obj)) {
        middleName = (string)properties["MiddleName"];
    };

    if (properties.TryGetValue("Surname", out obj)) {
        surname = (string)properties["Surname"];
    };

    if (properties.TryGetValue("SamAccountName", out obj)) {
        samAccountName = (string)properties["SamAccountName"];
    };

    if (String.IsNullOrEmpty(middleName)) {
        displayName = String.Format("{0} {1}", givenName, surname);

        if (String.IsNullOrEmpty(samAccountName)) {
            samAccountName = String.Format("{0}{1}", givenName[0], surname);
        };
    } else {
        displayName = String.Format("{0} {1}. {2}", givenName, middleName[0], surname);

        if (String.IsNullOrEmpty(samAccountName)) {
            samAccountName = String.Format("{0}{1}{2}", givenName[0], middleName[0], surname);
        };
    };

    samAccountName = samAccountName.ToLower();

    principal.DisplayName = displayName;
    principal.GivenName = givenName;
    principal.MiddleName = middleName;
    principal.SamAccountName = samAccountName;
    principal.Surname = surname;
    principal.UserPrincipalName = String.Format("{0}@dryforce.com", samAccountName);
}


推荐答案

   using (DirectoryEntry entry = (principal.GetUnderlyingObject() as DirectoryEntry))

购买。 NET设计人员为良好的方法命名设计了一支雪茄。您正在使用using语句处置基础对象。您猛拉了地板垫,使类工作正常的对象不再存在。这是一只死鹦鹉。等效的是,例如,放置StreamReader.BaseStream。尝试这么做之后,尝试从Kaboom读取它,无法从已处置的基础对象中读取。

Buy the .NET designers a cigar for good method naming. You are disposing the "underlying object" with the using statement. You jerked the floor mat, the object that makes the class work is no more. It is a dead parrot. An equivalent would be, say, disposing StreamReader.BaseStream. Trying to read from it after you did that is going to go Kaboom, can't read from a disposed underlying object.

处置它不是您的工作,您的代码没有创建它。通过省略 using 关键字来解决此问题。

It's not your job to dispose it, your code didn't create it. Fix the problem by omitting the using keyword.

这篇关于UserPrincipal.Save()导致ObjectDisposedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆