C#Base Class用于跟踪更改ADO.NET

时间:2014-05-06 00:56:50

标签: c# entity-framework ado.net

我在我的应用程序中使用Entity Framework和ChangeTracking实体,因此我可以在数据库中为每个添加,修改,删除(ColumnName,OriginalValue,NewValue等)提供审核日志。

我有一些函数不会使用Entity Framework,因为它非常慢,例如批量插入/更新和其他场景,而是我将使用存储过程ADO.NET。

为了跟踪Entity Framework和ADO.NET上的更改,我在考虑使用基类来自定义类,这些类将从DataReaders中填充,并且需要跟踪这些类的更改,因此我提出了:< / p>

public class NotifyPropertyChangeObject : INotifyPropertyChanged
    {
        /// <summary>
        /// Track changes or not.
        /// If we're working with DTOs and we fill up the DTO in the DAL we should not be tracking changes.
        /// </summary>
        private bool trackChanges = false;

        /// <summary>
        /// Changes to the object
        /// </summary>
        public List<TrackChange> Changes { get; private set; }

        /// <summary>
        /// Is the object dirty or not?
        /// </summary>
        public bool IsDirty
        {
            get { return Changes.Count > 0; }
            set { ; }
        }

        /// <summary>
        /// Event required for INotifyPropertyChanged
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// This constructor will initialize the change tracking
        /// </summary>
        public NotifyPropertyChangeObject()
        {
            // Change tracking default
            trackChanges = true;

            // New change tracking dictionary
            Changes = new List<TrackChange>();
        }

        /// <summary>
        /// Reset the object to non-dirty
        /// </summary>
        public void Reset()
        {
            Changes.Clear();
        }

        /// <summary>
        /// Start tracking changes
        /// </summary>
        public void StartTracking()
        {
            trackChanges = true;
        }

        /// <summary>
        /// Stop tracking changes
        /// </summary>
        public void StopTracking()
        {
            trackChanges = false;
        }

        /// <summary>
        /// Change the property if required and throw event
        /// </summary>
        /// <param name="variable"></param>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public void ApplyPropertyChange<T, F>(ref F field, Expression<Func<T, object>> property, F value)
        {
            // Only do this if the value changes
            if (field == null || !field.Equals(value))
            {
                // Get the property
                var propertyExpression = GetMemberExpression(property);
                if (propertyExpression == null)
                    throw new InvalidOperationException("You must specify a property");

                // Property name
                string propertyName = propertyExpression.Member.Name;


                // If change tracking is enabled, we can track the changes...
                if (trackChanges)
                {
                    // Change tracking

                    var track = Changes.Where(c => c.Name == propertyName).FirstOrDefault();
                    if (track == null)
                    {
                        track = new TrackChange();
                        track.Name = propertyName;
                        track.Original = field;
                        track.Value = value;
                        Changes.Add(track);
                    }
                    else
                    {
                        track.Name = propertyName;
                        track.Original = field;
                        track.Value = value;
                    }

                    //Changes[propertyName] = value;

                    // Notify change
                    NotifyPropertyChanged(propertyName);
                }

                // Set the value
                field = value;

            }
        }

        /// <summary>
        /// Get member expression
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public MemberExpression GetMemberExpression<T>(Expression<Func<T, object>> expression)
        {
            // Default expression
            MemberExpression memberExpression = null;

            // Convert
            if (expression.Body.NodeType == ExpressionType.Convert)
            {
                var body = (UnaryExpression)expression.Body;
                memberExpression = body.Operand as MemberExpression;
            }
            // Member access
            else if (expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                memberExpression = expression.Body as MemberExpression;
            }

            // Not a member access
            if (memberExpression == null)
                throw new ArgumentException("Not a member access", "expression");

            // Return the member expression
            return memberExpression;
        }

        /// <summary>
        /// The property has changed
        /// </summary>
        /// <param name="propertyName"></param>
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// Convert the changes to an XML string
        /// </summary>
        /// <returns></returns>
        public string ChangesToXml()
        {
            // Prepare base objects
            XDeclaration declaration = new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty);
            XElement root = new XElement("Changes");

            // Create document
            XDocument document = new XDocument(declaration, root);

            // Add changes to the document
            // TODO: If it's an object, maybe do some other things
            //foreach (KeyValuePair<string, object> change in Changes)
            //    root.Add(new XElement(change.Key, change.Value));

            // Get the XML
            return document.Document.ToString();
        }
    }

public class TrackChange
    {
        public string Name { get; set; }
        public object Original { get; set; }
        public object Value { get; set; }
    }

这样我就可以在两个数据上下文中保留审计日志功能。

使用ADO.NET保存数据时,我将使用一个函数将更改转换为存储过程参数,以便保存到AuditLog表中。

有谁知道这是一个不错的选择吗?

0 个答案:

没有答案