public override async Task Update(IPatch patch, string correlationIdentifier)
        {
            if (null == patch)
            {
                throw new ArgumentNullException(FileProvider.ArgumentNamePatch);
            }

            if (null == patch.ResourceIdentifier)
            {
                throw new ArgumentException(ProvisioningAgentResources.ExceptionInvalidPatch);
            }

            if (string.IsNullOrWhiteSpace(patch.ResourceIdentifier.Identifier))
            {
                throw new ArgumentException(ProvisioningAgentResources.ExceptionInvalidPatch);
            }

            if (null == patch.PatchRequest)
            {
                throw new ArgumentException(ProvisioningAgentResources.ExceptionInvalidPatch);
            }

            string informationStarting =
                string.Format(
                    CultureInfo.InvariantCulture,
                    FileProvisioningAgentResources.InformationPatching,
                    patch.ResourceIdentifier.SchemaIdentifier,
                    patch.ResourceIdentifier.Identifier);
            ProvisioningAgentMonitor.Instance.Inform(informationStarting, true, correlationIdentifier);

            PatchRequest2 patchRequest = patch.PatchRequest as PatchRequest2;
            if (null == patchRequest)
            {
                string unsupportedPatchTypeName = patch.GetType().FullName;
                throw new NotSupportedException(unsupportedPatchTypeName);
            }

            IRow row = await this.file.ReadRow(patch.ResourceIdentifier.Identifier);

            string rowSchema = null;
            if
            (
                    !row.Columns.TryGetValue(AttributeNames.Schemas, out rowSchema)
                ||  !string.Equals(rowSchema, patch.ResourceIdentifier.SchemaIdentifier, StringComparison.Ordinal)
            )
            {
                return;
            }

            IReadOnlyDictionary<string, string> columns;
            WindowsAzureActiveDirectoryGroup group = null;
            switch (rowSchema)
            {
                case SchemaIdentifiers.Core2EnterpriseUser:
                    ResourceFactory<Core2EnterpriseUser> userFactory = new UserFactory(row);
                    Core2EnterpriseUser user = userFactory.Create();
                    user.Apply(patchRequest);
                    ColumnsFactory<Core2EnterpriseUser> userColumnsFactory = new UserColumnsFactory(user);
                    columns = userColumnsFactory.CreateColumns();
                    break;

                case SchemaIdentifiers.WindowsAzureActiveDirectoryGroup:
                    ResourceFactory<WindowsAzureActiveDirectoryGroup> groupFactory = new GroupFactory(row);
                    group = groupFactory.Create();
                    group.Apply(patchRequest);
                    ColumnsFactory<WindowsAzureActiveDirectoryGroup> groupColumnsFactory = new GroupColumnsFactory(group);
                    columns = groupColumnsFactory.CreateColumns();
                    break;
                default:
                    throw new NotSupportedException(patch.ResourceIdentifier.SchemaIdentifier);
            }

            IRow rowReplacement = new Row(row.Key, columns);
            await this.file.ReplaceRow(rowReplacement);

            if (group != null)
            {
                await this.UpdateMembers(group, patch);
            }
        }
        public async Task TestReplacing()
        {
            string fileName = CommaDelimitedFileUnitTest.ComposeFileName();

            try
            {
                IReadOnlyCollection<string> columnNames =
                    Enumerable.Range(0, CommaDelimitedFileUnitTest.CountColumns)
                    .Select(
                        (int item) =>
                            item.ToString(CultureInfo.InvariantCulture))
                    .ToArray();

                IRow rowOne;
                ITabularFileAdapter fileStore = null;
                string replacementValue;
                try
                {
                    fileStore = new CommaDelimitedFileAdapter(fileName, columnNames);
                    Assert.IsTrue(File.Exists(fileName));

                    Dictionary<string, string> columnsWritten =
                        columnNames
                        .ToDictionary(
                            (string item) =>
                                item,
                            (string item) =>
                                Guid.NewGuid().ToString());

                    rowOne = await fileStore.InsertRow(columnsWritten);
                    Assert.IsNotNull(rowOne);
                    Assert.IsFalse(string.IsNullOrWhiteSpace(rowOne.Key));

                    IRow rowTwo = await fileStore.InsertRow(columnsWritten);
                    Assert.IsNotNull(rowTwo);
                    Assert.IsFalse(string.IsNullOrWhiteSpace(rowTwo.Key));

                    Assert.IsFalse(string.Equals(rowOne.Key, rowTwo.Key, StringComparison.OrdinalIgnoreCase));

                    string columnName = columnsWritten.Keys.Last();
                    replacementValue = Guid.NewGuid().ToString();
                    columnsWritten[columnName] = replacementValue;

                    IRow rowReplacment = new Row(rowOne.Key, columnsWritten);
                    await fileStore.ReplaceRow(rowReplacment);
                }
                finally
                {
                    if (fileStore != null)
                    {
                        fileStore.Dispose();
                        fileStore = null;
                    }
                }

                IReadOnlyCollection<string> lines = File.ReadAllLines(fileName);
                Assert.AreEqual(3, lines.LongCount());
                Assert.AreEqual(
                    1,
                    lines
                    .Where(
                        (string item) =>
                                item.StartsWith(rowOne.Key, StringComparison.OrdinalIgnoreCase)
                            &&  item.EndsWith(replacementValue, StringComparison.OrdinalIgnoreCase))
                    .LongCount());
            }
            finally
            {
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
            }
        }
        private static IRow FilterColumns(IRow row, IReadOnlyCollection<string> columnNames)
        {
            if (null == row)
            {
                throw new ArgumentNullException(FileProvider.ArgumentNameRow);
            }

            if (null == columnNames)
            {
                throw new ArgumentNullException(FileProvider.ArgumentNameColumnNames);
            }

            Dictionary<string, string> columns;
            if (row.Columns != null)
            {
                columns =
                    row
                    .Columns
                    .Where(
                        (KeyValuePair<string, string> columnItem) =>
                            columnNames
                            .Any(
                                (string columnNameItem) =>
                                    string.Equals(
                                        columnNameItem,
                                        columnItem.Key,
                                        StringComparison.Ordinal)))
                    .ToDictionary(
                        (KeyValuePair<string, string> item) =>
                            item.Key,
                        (KeyValuePair<string, string> item) =>
                            item.Value);
            }
            else
            {
                columns = null;
            }

            IRow result = new Row(row.Key, columns);
            return result;
        }