Click here to Skip to main content
15,896,339 members
Articles / Web Development / ASP.NET

Using Silverlight in Enterprise: RAD of User Friendly Database Access

Rate me:
Please Sign up or sign in to vote.
4.81/5 (19 votes)
31 Jul 2009CPOL8 min read 58.2K   7K   80  
This article introduces FulcrumWeb RAD Framework - A Silverlight UI Engine to build user friendly database driven applications
/********************************************************************
 *  FulcrumWeb RAD Framework - Fulcrum of your business             *
 *  Copyright (c) 2002-2009 FulcrumWeb, ALL RIGHTS RESERVED         *
 *                                                                  *
 *  THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      *
 *  FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        *
 *  COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       *
 *  AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  *
 *  AND PERMISSION FROM FULCRUMWEB. CONSULT THE END USER LICENSE    *
 *  AGREEMENT FOR INFORMATION ON ADDITIONAL RESTRICTIONS.           *
 ********************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Framework.Silverlight.Client.AppServer;

namespace Framework.Silverlight.Client
{
  /// <summary>
  /// Represents collection of Entities. 
  /// </summary>
  public class CxEntityList : IEnumerable, IxDataObject
  {
    private bool m_IsDisposed;
    private int m_ChangesCounter;

    //----------------------------------------------------------------------------
    /// <summary>
    /// Occurs when Attribute with depended attributes had changed.
    /// </summary>
    public event DxDependencyAttributeChanged DependencyAttributeChanged;

    //----------------------------------------------------------------------------
    /// <summary>
    /// Occurs when data had change.
    /// </summary>
    public event EventHandler DataChanged;

    //----------------------------------------------------------------------------
    /// <summary>
    /// Occurs when changes of data was commited.
    /// </summary>
    public event EventHandler DataCommited;

    //----------------------------------------------------------------------------
    /// <summary>
    /// Occurs when changes of data was reverted.
    /// </summary>
    public event EventHandler DataReverted;
    //----------------------------------------------------------------------------

    /// <summary>
    /// Gets list of CxBaseEntity.
    /// </summary>
    public ObservableCollection<CxBaseEntity> Entities { get; private set; }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Initializes a new instance of the CxEntityList class.
    /// </summary>
    public CxEntityList()
    {
      Entities = new ObservableCollection<CxBaseEntity>();
      Entities.CollectionChanged += Entities_CollectionChanged;
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DependencyAttributeChanged event.
    /// </summary>
    protected virtual void OnDependencyAttributeChanged(CxDependencyAttributeChangedEventArgs e)
    {
      if (DependencyAttributeChanged != null)
      {
        DependencyAttributeChanged(this, e);
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Handles CollectionChanged event.
    /// </summary>
    void Entities_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      if (e.Action == NotifyCollectionChangedAction.Add)
      {
        foreach (CxBaseEntity baseEntity in e.NewItems)
        {
          baseEntity.DataChanged += baseEntity_DataChanged;
          baseEntity.DataReverted += baseEntity_DataReverted;
          baseEntity.DataCommited += baseEntity_DataCommited;
          baseEntity.DependencyAttributeChanged += baseEntity_DependencyAttributeChanged;
        }
      }
      if (e.Action == NotifyCollectionChangedAction.Remove)
      {
        foreach (CxBaseEntity baseEntity in e.OldItems)
        {
          baseEntity.DataChanged -= baseEntity_DataChanged;
          baseEntity.DataReverted -= baseEntity_DataReverted;
          baseEntity.DataCommited -= baseEntity_DataCommited;
          baseEntity.DependencyAttributeChanged -= baseEntity_DependencyAttributeChanged;
          baseEntity.Dispose();
        }
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Handles CxBaseEntity.DependencyAttributeChanged
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void baseEntity_DependencyAttributeChanged(object sender, CxDependencyAttributeChangedEventArgs e)
    {
      OnDependencyAttributeChanged(new CxDependencyAttributeChangedEventArgs(e.ChangedAttributeId));
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Returns an enumerator that iterates through the collection.
    /// </summary>
    /// <returns>
    /// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
    /// </returns>
    public IEnumerator GetEnumerator()
    {
      return Entities.GetEnumerator();
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Handles the CxBaseEntity.DataChanged event.
    /// </summary>
    void baseEntity_DataChanged(object sender, EventArgs e)
    {
      m_ChangesCounter++;
      OnDataChanged();
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DataCommited event.
    /// </summary>
    void baseEntity_DataCommited(object sender, EventArgs e)
    {
      m_ChangesCounter--;
      if (m_ChangesCounter == 0)
      {
        OnDataCommited();
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DataReverted event.
    /// </summary>
    void baseEntity_DataReverted(object sender, EventArgs e)
    {
      m_ChangesCounter--;
      if (m_ChangesCounter == 0)
      {
        OnDataReverted();
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DataChanged event.
    /// </summary>
    protected virtual void OnDataChanged()
    {
      if (DataChanged != null)
      {
        DataChanged(this, EventArgs.Empty);
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DataReverted event.
    /// </summary>
    protected virtual void OnDataReverted()
    {
      if (DataReverted != null)
      {
        DataReverted(this, EventArgs.Empty);
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Raises the DataCommited event.
    /// </summary>
    protected virtual void OnDataCommited()
    {
      if (DataCommited != null)
      {
        DataCommited(this, EventArgs.Empty);
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Commits all the changes made to this DataObject since
    /// the last time AcceptChanges() was called.
    /// <param name="validate">True - validate befor accepting.</param>
    /// </summary>
    public void AcceptChanges(bool validate)
    {
      foreach (IxDataObject entity in Entities)
      {
        entity.AcceptChanges(validate);
      }
      m_ChangesCounter = 0;
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Commits all the changes made to this DataObject since
    /// the last time AcceptChanges() was called.
    /// </summary>
    public void AcceptChanges()
    {
      AcceptChanges(true);
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Rolls back all changes that have been made to the
    /// DataObject since the last time AcceptChanges() was called.
    /// </summary>
    public void RejectChanges()
    {
      foreach (IxDataObject entity in Entities)
      {
        entity.RejectChanges();
      }
      m_ChangesCounter = 0;
    }

    //----------------------------------------------------------------------------

    /// <summary>
    ///  Performs application-defined tasks associated with freeing, releasing,
    ///  or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
      if (!m_IsDisposed)
      {
        foreach (CxBaseEntity entity in Entities)
        {
          Entities.CollectionChanged -= Entities_CollectionChanged;
          entity.DataChanged -= baseEntity_DataChanged;
          entity.DataReverted -= baseEntity_DataReverted;
          entity.DataCommited -= baseEntity_DataCommited;
          entity.DependencyAttributeChanged -= baseEntity_DependencyAttributeChanged;
          entity.Dispose();
        }
        Entities.Clear();
        m_IsDisposed = true;
      }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Finds Entity with defined primary key(s).
    /// </summary>
    /// <param name="pkList">List of primary key(s) which need to find.</param>
    /// <returns>Found Entity or null.</returns>
    public CxBaseEntity FindEntityByPk(IList<CxAttributeSnapShot> pkList)
    {
      foreach (CxBaseEntity entity in Entities)
      {
        if (entity.ComparePk(pkList))
        {
          return entity;
        }
      }
      return null;
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Gets value that defines, has this entity uncommitted changes or not.
    /// </summary>
    public bool HasChanges
    {
      get { return m_ChangesCounter > 0; }
    }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Gets or sets value that defines there was DataObject is commited.
    /// </summary>
    public bool IsCommited { get; set; }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Returns true if the data list contains one, newly created entity 
    /// and this entity is newer commited.
    /// </summary>
    public bool IsNewEntity { get; internal set; }

    //----------------------------------------------------------------------------
    /// <summary>
    /// Refreshes entity by given CxExpressionResult.
    /// </summary>
    /// <param name="exprResult"></param>
    public void RefreshEntity( 
      CxExpressionResult exprResult)
    {
      Dictionary<string, object> pkList = new Dictionary<string, object>();
      foreach (KeyValuePair<CxClientAttributeMetadata, object> pair in exprResult.Entity)
      {
        if (pair.Key.PrimaryKey)
        {
          pkList.Add(pair.Key.Id, pair.Value);
        }
      }

      List<CxBaseEntity> entities = (from baseEntity in Entities
                                     where baseEntity.ComparePk(pkList)
                                     select baseEntity).ToList();
      if (entities.Count == 0)
        throw new ExApplicationException("Entity with given PK list does not exists.");

      entities[0].Refresh(exprResult);
    }

   
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions