Partially Modifying an XML serialized document.

Posted by Stacey on Stack Overflow See other posts from Stack Overflow or by Stacey
Published on 2010-03-19T19:41:35Z Indexed on 2010/03/19 20:01 UTC
Read the original article Hit count: 189

Filed under:
|
|
|

I have an XML document, several actually, that will be editable via a front-end UI. I've discovered a problem with this approach (other than the fact that it is using xml files instead of a database... but I cannot change that right now).

If one user makes a change while another user is in the process of making a change, then the second one's changes will overwrite the first.

I need to be able to request objects from the xml files, change them, and then submit the changes back to the xml file without re-writing the entire file. I've got my entire xml access class posted here (which was formed thanks to wonderful help from stackoverflow!)

using System;
using System.Linq;

using System.Collections;
using System.Collections.Generic;

namespace Repositories
{
    /// <summary>
    /// A file base repository represents a data backing that is stored in an .xml file.
    /// </summary>
    public partial class Repository<T> : IRepository
    {
        /// <summary>
        /// Default constructor for a file repository
        /// </summary>
        public Repository() { }

        /// <summary>
        /// Initialize a basic repository with a filename. This will have to be passed from a context to be mapped.
        /// </summary>
        /// <param name="filename"></param>
        public Repository(string filename)
        {
            FileName = filename;
        }

        /// <summary>
        /// Discovers a single item from this repository.
        /// </summary>
        /// <typeparam name="TItem">The type of item to recover.</typeparam>
        /// <typeparam name="TCollection">The collection the item belongs to.</typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TItem Single<TItem, TCollection>(Predicate<TItem> expression)
            where TCollection : IDisposable, IEnumerable<TItem>
        {
            using (var list = List<TCollection>())
            {
                return list.Single(i => expression(i));
            }
        }

        /// <summary>
        /// Discovers a collection from the repository,
        /// </summary>
        /// <typeparam name="TCollection"></typeparam>
        /// <returns></returns>
        public TCollection List<TCollection>() 
            where TCollection : IDisposable
        {
            using (var list = System.Xml.Serializer.Deserialize<TCollection>(FileName))
            {
                return (TCollection)list;
            }
        }

        /// <summary>
        /// Discovers a single item from this repository.
        /// </summary>
        /// <typeparam name="TItem">The type of item to recover.</typeparam>
        /// <typeparam name="TCollection">The collection the item belongs to.</typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public List<TItem> Select<TItem, TCollection>(Predicate<TItem> expression)
            where TCollection : IDisposable, IEnumerable<TItem>
        {
            using (var list = List<TCollection>())
            {
                return list.Where( i => expression(i) ).ToList<TItem>();
            }
        }

        /// <summary>
        /// Attempts to save an entire collection.
        /// </summary>
        /// <typeparam name="TCollection"></typeparam>
        /// <param name="collection"></param>
        /// <returns></returns>
        public Boolean Save<TCollection>(TCollection collection)
        {
            try
            {
                // load the collection into an xml reader and try to serialize it.
                System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
                xDoc.LoadXml(System.Xml.Serializer.Serialize<TCollection>(collection));

                // attempt to flush the file
                xDoc.Save(FileName);

                // assume success
                return true;
            }
            catch
            {
                return false;
            }
        }


        internal string FileName { get; private set; }
    }

    public interface IRepository
    {
        TItem Single<TItem, TCollection>(Predicate<TItem> expression) where TCollection : IDisposable, IEnumerable<TItem>;
        TCollection List<TCollection>() where TCollection : IDisposable;
        List<TItem> Select<TItem, TCollection>(Predicate<TItem> expression) where TCollection : IDisposable, IEnumerable<TItem>;

        Boolean Save<TCollection>(TCollection collection);
    }
}

© Stack Overflow or respective owner

Related posts about xml-serialization

Related posts about c#3.0