我在我的应用程序中使用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表中。
有谁知道这是一个不错的选择吗?