Beispiel #1
0
        /// <summary>
        /// Retrieve the values that a single property has gone through, most recent
        /// first (descending date order).
        /// </summary>
        public virtual IEnumerable <IChange <TValue, TPrincipal> > ChangesTo <TModel, TValue>(TModel model, Expression <Func <TModel, TValue> > property)
        {
            string typeName     = typeof(TModel).Name;
            string propertyName = property.GetPropertyName();
            string reference    = db.GetReferenceForObject(model);

            return(db.ObjectChanges
                   .Where(o => o.TypeName == typeName)
                   .Where(o => o.ObjectReference == reference)
                   .SelectMany(o => o.PropertyChanges)
                   .Where(p => p.PropertyName == propertyName)
                   .OrderByDescending(p => p.ObjectChange.ChangeSet.Timestamp)
                   .AsEnumerable()
                   .Select(p => new Change <TValue, TPrincipal>(bind <TValue>(p.Value), p.ObjectChange.ChangeSet.Author, p.ObjectChange.ChangeSet.Timestamp)));
        }
        /// <summary>
        /// Retrieve the values that a single property has gone through, most recent
        /// first (descending date order).
        /// </summary>
        public virtual IEnumerable<IChange<TValue, TPrincipal>> ChangesTo<TModel, TValue>(TModel model, Expression<Func<TModel, TValue>> property)
        {
            string typeName = typeof(TModel).Name;
            string propertyName = property.GetPropertyName();
            string propertyPrefix = propertyName + ".";
            string reference = historyContext.GetReferenceForObject(model);
            var propertyFunc = property.Compile();
            
            var objectChanges = changesTo(model)
                .SelectMany(o => o.PropertyChanges)
                .Where(p => p.PropertyName == propertyName || p.PropertyName.StartsWith(propertyPrefix))
                .AsEnumerable()
                .GroupBy(p => p.ObjectChange)
                .Select(g => new FilteredObjectChange<TPrincipal>(g.Key, g));

            // If the propert expression refers to a complex type then we will not have any changes
            // directly to that property. Instead we will see changes to sub-properties.
            // We retrieve the history differently for complex types, so here we distinguish which
            // case we are in by looking at the first change.
            var sample = objectChanges.SelectMany(o => o.PropertyChanges).FirstOrDefault();
            if (sample != null && sample.PropertyName.StartsWith(propertyPrefix))
            {
                // Construct a "seed" instance of the complex type, and then apply changes to it in order
                // to reconstruct the intermediate states.
                return applyChangesTo(HistoryHelpers.Instantiate<TValue>(), objectChanges, propertyName)
                    .OrderByDescending(c => c.Timestamp);
            }
            else
            {
                // Just directly bind the simple property values
                return objectChanges
                    .OrderByDescending(o => o.ChangeSet.Timestamp)
                    .SelectMany(o => o.PropertyChanges)
                    .Select(p => Change.FromObjectChange(binder.Bind<TValue>(p.Value), p.ObjectChange));
            }
        }
 protected virtual bool equalCollectionItems(object a, object b)
 {
     return((db.ObjectHasReference(a))
         ? (db.GetReferenceForObject(a) == db.GetReferenceForObject(b))
         : Equals(a, b));
 }