This project is read-only.

Fields not scaffolded but still audited?

Sep 29, 2010 at 9:25 PM

There are some table fields that I don't need to have audited, and I'm not sure how to exclude them.

Let's use a Vendors table as an example.

Vendors has a field VendorTypeId, which is linked to the table VendorTypes. There are also the PK field VendorId, and additional fields Vendor, Address, City, State, Postal, Country.

When I insert a new record, the following fields are audited:

  • VendorId
  • Vendor
  • VendorTypeId (shows as Vendor Type, with the proper vendor type shown, through AuditPropertyResolver)
  • Address
  • City
  • State
  • Postal
  • Country
  • Vendor Type

The ones I do not wish to show are Country and Vendor Type.

Is there something that allows these to be excluded?

I've tried setting <ScaffoldColumn(False)> in the metadata for each, with no success.

Thanks,

Bryant

Sep 29, 2010 at 9:37 PM

Hi Bryant,

If you download the latest version from the Source Code tab, there is a mechanism in place to allow you to do this. There is a property on the IAuditableDataContext (your LINQ to SQL or EF data context) called "PropertyAuditRules"

By default, I defined a rule for LINQ to SQL to only audit properties that have a [ColumnAttribute] on them. You will find the following if you view the source code for AuditableDataContext

PropertyAuditRules.Add((m, e) => m.HasAttribute(typeof(ColumnAttribute)));

With that in mind, you can add your own rule here, just make sure you call this method BEFORE auditing takes place... something like:

PropertyAuditRules.Add((m, e) => !m.HasAttribute(typeof(DoNotAuditAttribute)));

* NOTE the ! in that rule... this is saying DO NOT audit Properties with this rule, which is the opposite of the ColumnAttribute rule, which ONLY audits properties with said attribute.

You would need to write a custom attribute to use this, and place it on the properties you want to exclude.

public class DoNotAuditAttribute : Attribute {  }

 

Hoepfully that will get you started -- I haven't tested any of the code provided above -- unfortunately I haven't been working on a project that needed auditing in a long time. But I think that should work just fine for you.

-Matt

Sep 29, 2010 at 10:01 PM

Ok, I made the changes, but don't think I got everything correct. I'd only written one attributes class in the past, and copied it over for my usage here.

Here's where I am defining the attribute in the audit code:

	Protected Overloads Overrides Sub InsertAuditRecordToDatabase(ByVal record As AuditedEntity)

		PropertyAuditRules.Add(Function(m, e) Not m.HasAttribute(GetType(DoNotAuditAttribute)))

		Dim audit As New AuditRecord()

This is where I am adding the attribute to a metadata column:

	<DoNotAudit(True)> _
	Public Country As Object

And finally this is the attribute class itself:

Imports Microsoft.VisualBasic

Public Class DoNotAuditAttribute
	Inherits Attribute

	Public Property Audit() As [Boolean]
		Get
			Return m_Audit
		End Get
		Private Set(ByVal value As [Boolean])
			m_Audit = Value
		End Set
	End Property

	Private m_Audit As [Boolean]

	Public Sub New(ByVal show__1 As [Boolean])
		Audit = show__1
	End Sub
	' this will allow us to have a default set to allowing auditing
	Public Shared [Default] As New DoNotAuditAttribute(False)

End Class

Country still appears in the fields audited.

Apologies for ignorance. I'm already learning a ton here.

Thanks,

Bryant

Sep 29, 2010 at 10:10 PM

Hi Bryant,

A couple things to change here:

1) Don't put a boolean property in your DoNotAuditAttribute, since it won't be used for anything. Simply make it [DoNotAudit] not [DoNotAudit(true)]

2) You need to move the PropertyAuditRules() call BEFORE InsertAuditRecordToDatabase

There is another virtual method that you can override called "DefaultAuditDefinitions"

Try this:

	Protected Overloads Overrides Sub DefaultAuditDefinitions()

		PropertyAuditRules.Add(Function(m, e) Not m.HasAttribute(GetType(DoNotAuditAttribute)))


 

Sep 29, 2010 at 10:30 PM

The attribute now reads as follows:

 

Imports Microsoft.VisualBasic

Public Class DoNotAuditAttribute
	Inherits Attribute

End Class

 

The column that I do not want to audit is as follows:

	<DoNotAudit()> _
	Public Country As Object

DefaultAuditDefinitions is also where you designate which tables are to be audited, correct?

If DefaultAuditDefinitions reads as follows ...

	Protected Overrides Sub DefaultAuditDefinitions()
		PropertyAuditRules.Add(Function(m, e) Not m.HasAttribute(GetType(DoNotAuditAttribute)))
		Me.Vendors.Audit()
	End Sub

... then a record is created in AuditRecords, but associated records are not generated in AuditRecordFields. 

I tried with the PropertyAuditRules line coming at the beginning and end of DefaultAuditDefinitions.

Sep 29, 2010 at 10:41 PM

Ah darn, I see the problem... Unfortunately we are going to have to hack a little bit to try to get this working... The problem is that if ANY of the PropertyAuditRules return false, we skip the property for auditing, so we need to try and group the 2 AuditRules together... hopefully this will fix it.

I have to write this in C# I'm afraid since I'm not very good at VB...

protected override void DefaultAuditDefinitions()

{

PropertyAuditRules.Clear();

PropertyAuditRules.Add((m, e) => m.HasAttribute(typeof(ColumnAttribute)) && !m.HasAttribute(typeof(DoNotAuditAttribute)));

}


 

Sep 30, 2010 at 12:58 AM

This still creates the AuditRecord, with no associated records in AuditRecordFields for each field inserted.

I copied the code into a C# converter, and this is what it returned -- can you make sure it's correct, as far as you can tell, in VB.NET?

		PropertyAuditRules.Clear()

		PropertyAuditRules.Add(Function(m, e) m.HasAttribute(GetType(ColumnAttribute)) AndAlso Not m.HasAttribute(GetType(DoNotAuditAttribute)))