我正在使用Linq To Sql并尝试保留更改历史记录并存储这些数据库。
我知道有这样的框架,例如DoddleAudit,但它对我来说太麻烦和臃肿,所以我正在尝试创建自己的。
这就是我迄今为止所拥有的。我正在寻找一种方法来使重复代码更具可重用性:
protected void InsertAuditRecordToDatabase(ModifiedMemberInfo[] changes, object entity)
{
Type type = entity.GetType();
PropertyInfo key;
key = type.GetProperties()
.Where(o =>
o.GetCustomAttributes(typeof(ColumnAttribute), true)
.Any(a=>((ColumnAttribute)a).IsPrimaryKey)).SingleOrDefault();
AuditRecord audit = new AuditRecord();
audit.Action = (byte)AuditAction.Update;
audit.AuditDate = DateTime.Now;
audit.AssociationTable = null;
audit.AssociationTableKey = null;
audit.EntityTable = type.Name;
audit.EntityTableKey = int.Parse(key.GetValue(entity, null).ToString());
audit.UserName = HttpContext.Current.User.Identity.Name;
if (string.IsNullOrEmpty(audit.UserName))
audit.UserName = "Anonymous";
foreach (ModifiedMemberInfo mmi in changes)
{
AuditRecordField field = new AuditRecordField();
if (!excludedFieldNamesFromAudit.Any(x => x.Equals(mmi.Member.Name, StringComparison.OrdinalIgnoreCase)))
{
field.MemberName = mmi.Member.Name;
field.OldValue = (mmi.OriginalValue != null ? mmi.OriginalValue.ToString() : string.Empty);
field.NewValue = (mmi.CurrentValue != null ? mmi.CurrentValue.ToString() : string.Empty);
if ((field.OldValue != null && !field.OldValue.Equals(field.NewValue)) ||
(field.OldValue == null && field.NewValue != null))
{
// Special handling
if (field.MemberName.Equals("EUAMemberTypeId"))
{
int oldInt;
OrganisationSubType oldValue = null;
if(int.TryParse(field.OldValue, out oldInt))
oldValue = this.OrganisationSubTypes.SingleOrDefault(m => m.Id == oldInt);
field.OldValue = oldValue != null ? oldValue.Name : string.Empty;
int newInt;
OrganisationSubType newValue = null;
if(int.TryParse(field.NewValue, out newInt))
newValue = this.OrganisationSubTypes.SingleOrDefault(m => m.Id == newInt);
field.NewValue = newValue != null ? newValue.Name : string.Empty;
}
if (field.MemberName.Equals("ContactPersonStaffId"))
{
int oldInt;
OrganisationStaff oldValue = null;
if (int.TryParse(field.OldValue, out oldInt))
oldValue = this.OrganisationStaffs.SingleOrDefault(m => m.Id == oldInt);
field.OldValue = oldValue != null ? oldValue.Contact.FullName : string.Empty;
int newInt;
OrganisationStaff newValue = null;
if (int.TryParse(field.NewValue, out newInt))
newValue = this.OrganisationStaffs.SingleOrDefault(m => m.Id == newInt);
field.NewValue = newValue != null ? newValue.Contact.FullName : string.Empty;
}
if (field.MemberName.Equals("CountryId"))
{
int oldInt;
Country oldValue = null;
if (int.TryParse(field.OldValue, out oldInt))
oldValue = this.Countries.SingleOrDefault(m => m.Id == oldInt);
field.OldValue = oldValue != null ? oldValue.Name : string.Empty;
int newInt;
Country newValue = null;
if (int.TryParse(field.NewValue, out newInt))
newValue = this.Countries.SingleOrDefault(m => m.Id == newInt);
field.NewValue = newValue != null ? newValue.Name : string.Empty;
}
// Save it to the DB
audit.AuditRecordFields.Add(field);
}
}
}
if (audit.AuditRecordFields.Count > 0)
this.AuditRecords.InsertOnSubmit(audit);
}
如您所见,这段代码正在重复:
if (field.MemberName.Equals("CountryId"))
{
int oldInt;
Country oldValue = null;
if (int.TryParse(field.OldValue, out oldInt))
oldValue = this.Countries.SingleOrDefault(m => m.Id == oldInt);
field.OldValue = oldValue != null ? oldValue.Name : string.Empty;
int newInt;
Country newValue = null;
if (int.TryParse(field.NewValue, out newInt))
newValue = this.Countries.SingleOrDefault(m => m.Id == newInt);
field.NewValue = newValue != null ? newValue.Name : string.Empty;
}
重复的模式是:
Countries
Country
m => m.ID == oldInt
oldValue.Name
我希望这可以用一些通用的表达法术来完成,但我似乎无法弄明白。
答案 0 :(得分:1)
这应该按照你的意愿行事。
您面临的挑战之一是,在解析字符串时,您希望在创建变量之前使用int参数的表达式。如果您已经创建了在创建表达式时创建的变量,那么它可以引用该变量,并且您的过程会更简单。
我通过在将字符串解析为int变量后动态构建表达式来解决这个问题。
protected void InsertAuditRecordToDatabase(ModifiedMemberInfo[] changes, object entity)
{
Type type = entity.GetType();
PropertyInfo key;
key = type.GetProperties()
.Where(o =>
o.GetCustomAttributes(typeof(ColumnAttribute), true)
.Any(a => ((ColumnAttribute)a).IsPrimaryKey)).SingleOrDefault();
AuditRecord audit = new AuditRecord();
audit.Action = (byte)AuditAction.Update;
audit.AuditDate = DateTime.Now;
audit.AssociationTable = null;
audit.AssociationTableKey = null;
audit.EntityTable = type.Name;
audit.EntityTableKey = int.Parse(key.GetValue(entity, null).ToString());
audit.UserName = HttpContext.Current.User.Identity.Name;
if (string.IsNullOrEmpty(audit.UserName))
audit.UserName = "Anonymous";
foreach (ModifiedMemberInfo mmi in changes)
{
AuditRecordField field = new AuditRecordField();
if (!excludedFieldNamesFromAudit.Any(x => x.Equals(mmi.Member.Name, StringComparison.OrdinalIgnoreCase)))
{
field.MemberName = mmi.Member.Name;
field.OldValue = (mmi.OriginalValue != null ? mmi.OriginalValue.ToString() : string.Empty);
field.NewValue = (mmi.CurrentValue != null ? mmi.CurrentValue.ToString() : string.Empty);
if ((field.OldValue != null && !field.OldValue.Equals(field.NewValue)) ||
(field.OldValue == null && field.NewValue != null))
{
// Special handling
if (field.MemberName.Equals("EUAMemberTypeId"))
{
field.OldValue = GetDescription(this.OrganisationSubTypes, field.OldValue, m => m.Id, m => m != null ? m.Name : string.Empty);
field.NewValue = GetDescription(this.OrganisationSubTypes, field.NewValue, m => m.Id, m => m != null ? m.Name : string.Empty);
}
if (field.MemberName.Equals("ContactPersonStaffId"))
{
field.OldValue = GetDescription(this.OrganisationStaffs, field.OldValue, m => m.Id, m => m != null ? m.Contact.FullName : string.Empty);
field.NewValue = GetDescription(this.OrganisationStaffs, field.NewValue, m => m.Id, m => m != null ? m.Contact.FullName : string.Empty);
}
if (field.MemberName.Equals("CountryId"))
{
field.OldValue = GetDescription(this.Countries, field.OldValue, m => m.Id, m => m != null ? m.Name : string.Empty);
field.NewValue = GetDescription(this.Countries, field.NewValue, m => m.Id, m => m != null ? m.Name : string.Empty);
}
// Save it to the DB
audit.AuditRecordFields.Add(field);
}
}
}
if (audit.AuditRecordFields.Count > 0)
this.AuditRecords.InsertOnSubmit(audit);
}
public static string GetDescription<T, TProp>(Table<T> thisTable, string searchParam, Expression<Func<T, TProp>> searchExpression, Expression<Func<T, string>> descriptionExpression)
where T : class
{
if (!(searchExpression.Body is MemberExpression))
{
throw new ArgumentException("Search Expression must be a MemberExpression (i.e v => v.Id)", "searchExpression");
}
else
{
int searchValue;
if (int.TryParse(searchParam, out searchValue))
{
var equalityExpression = Expression.Equal(searchExpression.Body, Expression.Constant(searchValue));
var lambdaExpression = Expression.Lambda<Func<T, bool>>(equalityExpression, searchExpression.Parameters);
// the passed-in expression must resemble v => v.Id
// the generated expression will resemble v => v.Id == 5
var value = thisTable.SingleOrDefault(lambdaExpression);
return descriptionExpression.Compile()(value);
}
return string.Empty;
}
}