Setting values that started null

Sep 12, 2012 at 11:08 PM
Edited Sep 13, 2012 at 2:34 PM

I am having a little trouble how to correctly do something. I am attempting to do the example you have on your front page of setting a title. It works fine if the user has a existing tile and I want to change it, but if they user does not have a title set (user.Title starts as "null") the update is never performed. If i just put anything in the title field first by hand it will correctly update, but if I blank it out it again silently fails to update.

I traced the problem to DirectoryObjectBase.GetChanges(object, IObjectMapping, OriginalValuesCollection)

        public static IEnumerable<DirectoryAttributeModification> GetChanges(object instance, IObjectMapping mapping, OriginalValuesCollection collection)
        {
            if (collection == null || collection.Count == 0)
            {
                foreach (var property in mapping.GetUpdateablePropertyMappings())
                {
                    yield return property.GetDirectoryAttributeModification(instance);
                }
            }
            else
            {
                foreach (var updateablePropertyMapping in mapping.GetUpdateablePropertyMappings())
                {
                    var propertyName = updateablePropertyMapping.PropertyName;
                    object value = collection[propertyName];
                    DirectoryAttributeModification modification;
                    if (value != null && !updateablePropertyMapping.IsEqual(instance, value, out modification))
                    {
                        yield return modification;
                    }
                }
            }
        }

The issue is if the old value was not set (or was set then had the information cleared out by hand)  "object value = collection[propertyName];" will return null, that then makes the if statment fail.

Why are you checking for value != null in that if statement?

 

Here is the code for my main

using System;
using System.Linq;
using LinqToLdap;

namespace LinqToLdapTest
{
    class Program { static void Main()
        {
            var config = new LdapConfiguration();
            var configuration = config.ConfigureFactory("vw.local");
           
            using (var context = new DirectoryContext(config))
            {
                context.Log = Console.Out;

                var user = context.Query<User>()
                    .Where(u => u.CommonName == "LinqToLdapTest")
                    .FirstOrDefault();
                Console.WriteLine(user.WhenChanged);

                user.Title = "Just Promoted";

                User updated = context.Update(user);
                Console.WriteLine(updated.WhenChanged);
            }
        }
    }
}

Here is the code for User

using LinqToLdap.Mapping;
using System;
using System.Security.Principal;


[DirectorySchema("CN=Users,DC=vw,DC=local", ObjectClass = "User")]
public class User : DirectoryObjectBase
{
    [DistinguishedName]
    public string DistinguishedName { get; set; }

    [DirectoryAttribute("cn", ReadOnly = true)]
    public string CommonName { get; set; }

    [DirectoryAttribute]
    public string Title { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public Guid ObjectGuid { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public SecurityIdentifier ObjectSid { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public DateTime WhenChanged { get; set; }
}

And here is what the console outputs

Expression: value(LinqToLdap.DirectoryQuery`1[User]).Where(u => (u.CommonName == "LinqToLdapTest")).FirstOrDefault()
Search Request >
Filter: (&(objectClass=User)(cn=LinqToLdapTest))
Attributes: cn, Title, ObjectGuid, ObjectSid, WhenChanged, distinguishedname
Naming Context: CN=Users,DC=vw,DC=local
Scope: Subtree
Types Only: False
Controls:
Page Size: 1
Page Cookie Length: 0
Page Control Is Critical: True
Page Control OID: 1.2.840.113556.1.4.319


9/12/2012 9:55:40 PM
9/12/2012 9:55:40 PM
Coordinator
Oct 5, 2012 at 3:35 AM
Edited Oct 5, 2012 at 3:35 AM

Hi leftler,

I was originally checking for null to protect against saving attributes that don't exist as part of that object's schema.  However, I realize that is an edge case and should be handled by the developer / LDAP administrator.  I've checked in the fix that removes the null check.