auditing

Posts   
 
    
gj1118
User
Posts: 30
Joined: 21-Jul-2010
# Posted on: 29-Jun-2012 01:31:50   

Hi ,

I downloaded the Auditing example from the samples section. I think I have done as I should but my Audit data is not being persisted. For your kind reference I am attaching the database table script, here.

This is the Code that I have

using System;
using System.Collections.Generic;
using System.Data;
using DataLayer.EntityClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace Vantive.Auditors
{
    [DependencyInjectionInfo(typeof(ContactEntity), "AuditorToUse")]
    [Serializable]
    public class ContactEntityAuditor:AuditorBase
    {
        #region Class Member Declarations
        /// <summary>
        /// Used to set the audit action type
        /// </summary>
        private enum AuditType
        {
            DeleteOfEntity=1,
            DirectDeleteOfEntities,
            DirectUpdateOfEntities,
            DereferenceOfRelatedEntity,
            ReferenceOfRelatedEntity,
            EntityFieldGet,
            EntityFieldSet,
            InsertOfNewEntity,
            UpdateOfExistingEntity,
            LoadOfExistingEntity
        }

        // used to collect auditInfo entities
        private List<AuditInfoEntity> _auditInfoEntities;       
        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ContactEntityAuditor"/> class.
        /// </summary>
        public ContactEntityAuditor()
        {
            _auditInfoEntities = new List<AuditInfoEntity>();
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Gets the current user ID from Session.
        /// </summary>
        /// <returns>Current logged-in user's ID</returns>
        private int GetCurrentUserID()
        {
            return 1;
        }

        /// <summary>
        /// Constructs the audit info.
        /// </summary>
        /// <param name="affectedEntityName">Name of the affected entity.</param>
        /// <param name="actionType">Type of the action.</param>
        /// <param name="actionData">The action data.</param>
        /// <returns></returns>
        private AuditInfoEntity ConstructAuditInfo(string affectedEntityName, AuditType actionType, string actionData)
        {
            // create a new audit unit
            AuditInfoEntity auditInfo = new AuditInfoEntity();
            auditInfo.AffectedEntityName = affectedEntityName;
            auditInfo.ActionDateTime = DateTime.Now;
            auditInfo.AuditActionTypeId = (int)actionType;
            auditInfo.UserId = GetCurrentUserID();
            auditInfo.ActionData = actionData;

            return auditInfo;
        }

        /// <summary>
        /// Adds one audit entry to auditInfo entities.
        /// </summary>
        /// <param name="auditInfo">The audit info.</param>
        private void AddAuditEntryToList(AuditInfoEntity auditInfo)
        {
            // adds for further DB persist
            _auditInfoEntities.Add(auditInfo);
        }

        /// <summary>
        /// Adds one audit entry to auditInfo entities.
        /// </summary>
        /// <param name="affectedEntityName">Name of the affected entity.</param>
        /// <param name="actionType">Type of the action.</param>
        /// <param name="actionData">The action data.</param>
        private void AddAuditEntryToList(string affectedEntityName, AuditType actionType, string actionData)
        {
            // create a new audit unit
            AuditInfoEntity auditInfo = ConstructAuditInfo(affectedEntityName, actionType, actionData);         

            // adds for further DB persist
            AddAuditEntryToList(auditInfo);
        }

        /// <summary>
        /// Direct persists the audit info. This method is used by methods that don't belong to a transaction
        /// like AuditLoadOfEntity, AuditDirectDeleteOfEntities and AuditDirectUpdateOfEntites
        /// </summary>
        /// <param name="auditInfo">The audit info.</param>
        private void DirectPersistAuditInfo(AuditInfoEntity auditInfo)
        {
            auditInfo.Save();           
        }

        /// <summary>
        /// Gets the primary key info from entity.
        /// </summary>
        /// <param name="entity">A valid instance of IEntity object.</param>
        /// <returns>Formatted string contained PK fields of the given entity</returns>
        private string GetPrimaryKeyInfoFromEntity(IEntityCore entity)
        {
            // gets primary key fields
            List<IEntityField> pkFields = ((IEntity)entity).PrimaryKeyFields;

            // collect PK fields if the entity isn't new
            string strPKEntityInfo = string.Empty;
            if (!entity.IsNew)
            {
                // construct formatted string with pk fields
                strPKEntityInfo = "PK(";
                foreach (IEntityField pkField in pkFields)
                {
                    strPKEntityInfo += string.Format("{0}:{1}, ", pkField.Name, pkField.CurrentValue.ToString());
                }

                // delete the extra ", " and ends with ")"
                strPKEntityInfo = strPKEntityInfo.Remove(strPKEntityInfo.Length - 2, 2);
                strPKEntityInfo += ")";
            }

            // returns PK info
            return strPKEntityInfo;
        }
        #endregion

        #region Public Audit methods
        /// <summary>
        /// Audits the successful delete of an entity from the database
        /// </summary>
        /// <param name="entity">The entity which was deleted.</param>
        /// <remarks>As the entity passed in was deleted succesfully, reading values from the 
        /// passed in entity is only possible in this routine. After this call, the
        /// state of the entity will be reset to Deleted again and reading the fields 
        /// will result in an exception. It's also recommended not to reference
        /// the passed in entity in any audit entity you might want to persist as the entity doesn't 
        /// exist anymore in the database.</remarks>
        public override void AuditDeleteOfEntity(IEntityCore entity)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            AddAuditEntryToList(
                entity.LLBLGenProEntityName, 
                AuditType.DeleteOfEntity,
                GetPrimaryKeyInfoFromEntity(entity));       
        }

        /// <summary>
        /// Audits the successful load of an entity from the database
        /// </summary>
        /// <param name="entity">The entity which was loaded.</param>
        public override void AuditLoadOfEntity(IEntityCore entity)
        {
            /// Direct persist audit info to DB, because if the LoadOfEntity doesn't belong to a 
            /// outside persist operation, the auditInfo wont be saved.
            /// Be aware that if an EntityCollection is fetched. This method will create a AuditInfoEntity
            /// for each one of LoadEntity. Recommended to filter this operation as you project nature requieres.
            /// 
            /// This routine is documented for auditInfo table readability. Uncomment below code to test it.

            /*
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if (entity is AuditInfoEntity)
            {
                return;
            }
            
            // construct audit info entity
            AuditInfoEntity auditInfo = ConstructAuditInfo(
                entity.LLBLGenProEntityName,
                AuditType.LoadOfExistingEntity,
                GetPrimaryKeyInfoFromEntity(entity));

            // persist to DB
            DirectPersistAuditInfo(auditInfo);          
             */
        }

        /// <summary>
        /// Audits the successful direct delete of entities in the database
        /// </summary>
        /// <param name="typeOfEntity">The type of entity of which entities were deleted.</param>
        /// <param name="filter">The filter to filter out the entities to delete. Can be null and can 
        /// be an IPredicateExpression.</param>
        /// <param name="relations">The relations to use with the filter. Can be null.</param>
        /// <param name="numberOfEntitiesDeleted">The number of entities deleted.</param>
        public override void AuditDirectDeleteOfEntities(Type typeOfEntity, IPredicate filter, 
            IRelationCollection relations, int numberOfEntitiesDeleted)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(typeOfEntity == typeof(AuditInfoEntity))
            {
                return;
            }

            // get filter's queryText
            string strFilter = filter.ToQueryText();

            // construct parameters info
            string strParameters = string.Empty;
            foreach (IDataParameter param in filter.Parameters)
            {
                strParameters += (param.ParameterName + "=" + param.Value.ToString() + ". ");
            }

            // construct audit info entity
            AuditInfoEntity auditInfo = ConstructAuditInfo(
                typeOfEntity.FullName, 
                AuditType.DirectDeleteOfEntities,
                string.Format("deleteFilter: {0}.  filterParameters: {1}", strFilter, strParameters));

            // add to audit-info-to-save
            AddAuditEntryToList(auditInfo);
        }

        /// <summary>
        /// Audits the successful dereference of related entity from the entity passed in.
        /// </summary>
        /// <param name="entity">The entity of which the related entity was dereferenced from.</param>
        /// <param name="relatedEntity">The related entity which was dereferenced from entity</param>
        /// <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related 
        /// entity for which the related entity was dereferenced.</param>
        public override void AuditDereferenceOfRelatedEntity(IEntityCore entity, IEntityCore relatedEntity, 
            string mappedFieldName)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            AddAuditEntryToList(
                entity.LLBLGenProEntityName, 
                AuditType.DereferenceOfRelatedEntity, 
                string.Format("{0}. RelatedEntityName: {1}. MappedFieldName: {2}",
                    GetPrimaryKeyInfoFromEntity(entity), relatedEntity.LLBLGenProEntityName, mappedFieldName));
        }

        /// <summary>
        /// Audits the succesful direct update of entities in the database.
        /// </summary>
        /// <param name="entity">The entity with the changed values which is used to produce the update 
        /// query.</param>
        /// <param name="filter">The filter to filter out the entities to update. Can be null and can be an 
        /// IPredicateExpression.</param>
        /// <param name="relations">The relations to use with the filter. Can be null.</param>
        /// <param name="numberOfEntitiesUpdated">The number of entities updated.</param>
        public override void AuditDirectUpdateOfEntities(IEntityCore entity, IPredicate filter, 
            IRelationCollection relations, int numberOfEntitiesUpdated)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            // get filter's queryText
            string strFilter = filter.ToQueryText();

            // construct parameters info
            string strParameters = string.Empty;
            foreach (IDataParameter param in filter.Parameters)
            {
                strParameters += (param.ParameterName + "=" + param.Value.ToString() + ". ");
            }

            // construct update-new-values info of the direct update
            string updatedFields = string.Empty;
            foreach (IEntityField field in ((IEntity)entity).Fields)
            {
                if (field.IsChanged)
                {
                    updatedFields += (field.Name + "=" + field.CurrentValue.ToString() + ". ");
                }
            }

            // construc audit info entity
            AuditInfoEntity auditInfo = ConstructAuditInfo(
                entity.LLBLGenProEntityName, 
                AuditType.DirectUpdateOfEntities,
                string.Format("updatedFields: {0}  updateFilter: {1}.  filterParameters: {2}", updatedFields, strFilter, strParameters));

            // add to audit-info-to-save
            AddAuditEntryToList(auditInfo);
        }

        /// <summary>
        /// Audits when an entity field is get succesfully.
        /// </summary>
        /// <param name="entity">The entity a field was get.</param>
        /// <param name="fieldIndex">Index of the field which got.</param>
        public override void AuditEntityFieldGet(IEntityCore entity, int fieldIndex)
        {
            /// NOTE: Uncomment this you want to track the got fields by an user. 
            /// This was commented to avoid hundreds of irrelevant audit info.

            /*
            
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if (entity is AuditInfoEntity)
            {
                return;
            }
            
            AddAuditEntryToList(
                entity.LLBLGenProEntityName, 
                AuditType.EntityFieldGet,
                string.Format("{0}. FieldGet: {1}",
                    GetPrimaryKeyInfoFromEntity(entity),
                    ((IEntity)entity).Fields[fieldIndex].Name));
             * */
        }

        /// <summary>
        /// Audits when an entity field is set succesfully to a new value.
        /// </summary>
        /// <param name="entity">The entity a field was set to a new value.</param>
        /// <param name="fieldIndex">Index of the field which got a new value.</param>
        /// <param name="originalValue">The original value of the field with the index passed in 
        /// before it received a new value.</param>
        public override void AuditEntityFieldSet(IEntityCore entity, int fieldIndex, object originalValue)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            // used to store the change experimented by a field.
            string originalValueAsString = string.Empty;
            string currentValue = string.Empty;
            
            // sets VALUE OR NULL for originalValue and uses it as string.
            if (originalValue != null)
            {
                originalValueAsString = originalValue.ToString();
            }
            else
            {
                originalValueAsString = "NULL";
            }

            // sets VALUE OR NULL for currentValue and uses it as string.
            if (entity.GetCurrentFieldValue(fieldIndex) != null)
            {
                currentValue = entity.GetCurrentFieldValue(fieldIndex).ToString();
            }
            else
            {
                currentValue = "NULL";
            }


            // post the field change info
            AddAuditEntryToList(
                entity.LLBLGenProEntityName,
                AuditType.EntityFieldSet,
                string.Format("{0}. FieldSet: {1}. OriginalValue: {2}. CurrentValue: {3}",
                    GetPrimaryKeyInfoFromEntity(entity),
                    ((IEntity) entity).Fields[fieldIndex].Name, 
                    originalValueAsString, currentValue));          
        }

        /// <summary>
        /// Audits the successful insert of a new entity into the database.
        /// </summary>
        /// <param name="entity">The entity saved successfully into the database.</param>
        public override void AuditInsertOfNewEntity(IEntityCore entity)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }


            AddAuditEntryToList(
                entity.LLBLGenProEntityName,
                AuditType.InsertOfNewEntity,
                GetPrimaryKeyInfoFromEntity(entity));           
        }

        /// <summary>
        /// Audits the successful reference of related entity from the entity passed in.
        /// </summary>
        /// <param name="entity">The entity of which the related entity was dereferenced from.</param>
        /// <param name="relatedEntity">The related entity which was dereferenced from entity</param>
        /// <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related 
        /// entity for which the related entity was referenced.</param>
        public override void AuditReferenceOfRelatedEntity(IEntityCore entity, IEntityCore relatedEntity, string mappedFieldName)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            AddAuditEntryToList(
                entity.LLBLGenProEntityName,
                AuditType.InsertOfNewEntity,
                string.Format("{0}. RelatedEntityName: {0}. MappedFieldName: {1}",
                    GetPrimaryKeyInfoFromEntity(entity), relatedEntity.LLBLGenProEntityName, mappedFieldName));
        }

        /// <summary>
        /// Audits the successful update of an existing entity in the database
        /// </summary>
        /// <param name="entity">The entity updated successfully in the database.</param>
        public override void AuditUpdateOfExistingEntity(IEntityCore entity)
        {
            // avoid to audit into AuditInfoEntity (this would create an overflow effect). This is necessary if this auditor is injected into 
            // all entities, thus also in the AuditInfoEntity
            if(entity is AuditInfoEntity)
            {
                return;
            }

            AddAuditEntryToList(
                entity.LLBLGenProEntityName,
                AuditType.UpdateOfExistingEntity,
                GetPrimaryKeyInfoFromEntity(entity));
        }

        /// <summary>
        /// Gets the audit entities to save. Audit entities contain the audit information stored inside this auditor.
        /// </summary>
        /// <returns>The list of audit entities to save, or null if there are no audit entities to save</returns>
        /// <remarks>Do not remove the audit entities and audit information from this auditor when this method is 
        /// called, as the transaction in which the save takes place can fail and retried which will result in another call 
        /// to this method</remarks>
        public override System.Collections.IList GetAuditEntitiesToSave()
        {
            return _auditInfoEntities;
        }

        /// <summary>
        /// The transaction with which the audit entities requested from GetAuditEntitiesToSave were saved.
        /// Use this method to clear any audit data in this auditor as all audit information is persisted successfully.
        /// </summary>
        public override void TransactionCommitted()
        {
            _auditInfoEntities.Clear();
        }
        #endregion
    }
}

and this is from my app.config

<?xml version="1.0"?>
<configuration>
    <configSections>
     <section name="Auditing" type="SD.LLBLGen.Pro.ORMSupportClasses.DependencyInjectionSectionHandler, SD.LLBLGen.Pro.ORMSupportClasses.NET20, Version=3.1.0.0, Culture=neutral, PublicKeyToken=ca73b74ba4e3ff27"/>
 </configSections>

  <Auditing>
    <additionalAssemblies>
      <assembly filename="Vantive.Auditors.dll"/>
    </additionalAssemblies>
  </Auditing>  

 <appSettings>
        <add key="ConnectionString.SQL Server (SqlClient)" value="data source=***;initial catalog=master;User ID=**;Password=**;persist security info=False;packet size=4096"/>
 </appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
 </configuration>

I have also made sure that there are proper references in place.

Please suggest.

Thanks and regards gagan

Attachments
Filename File size Added on Approval
AuditTables.sql 2,447 29-Jun-2012 01:32.26 Approved
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 29-Jun-2012 07:24:49   

Hi gagan,

I don't think the problem is in the db or in your auditor, but maybe in the way the auditor is injected in the entity instance. Maybe it isn't injected at all. To prove that, put a breakpoint at the Auditor constructor, or debug your app and see if the involved entity has something set in the .AuditorToUse property. You can also set this property manually.

Said that, please try to specify the full-name version of the assembly in the config. See the "Important" box in this documentation section.

David Elizondo | LLBLGen Support Team
gj1118
User
Posts: 30
Joined: 21-Jul-2010
# Posted on: 03-Jul-2012 21:29:54   

works.. thanks team .. simple_smile

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Jul-2012 06:36:20   

gj1118 wrote:

works.. thanks team .. simple_smile

Good it worked wink You are welcome!

David Elizondo | LLBLGen Support Team