1

My application uses Audit.NET with Audit.EntityFramework for audit logging data changes. For the purpose of facilitation the creation of audit log / data changes visualisation, I decided to log changes from a few tables into a single one. Long story short: I defined a state machine for my item and I'm logging whats happening with it from when it first appears in my system till when I dispose it.

In order to demonstrate the issues that I'm struggling with, I create a test REST app and made it available on GitHub repository.

The application tracks the lifetime of articles, where an article can come to the system by:

  • an article is directly added and linked to a publication - in short, it is ACCEPTED
  • an article proposal is added - in short, it is PROPOSED
  • a PROPOSED article can be accepted for addition to a publication - in short, it is ACCEPT_PROPOSAL

For some more details, check the public enum ProcessAction.

How to reproduce

  1. Clone the repo
  2. Create the DB and the user - creation SQL code is contained in a comment in TestDbContext.cs
  3. Run the DB migration
  4. Start the application
  5. Call all endpoints from TestsController.cs in the order they appear - here are direct links (HTTP GET):
    1. Mew Publication: http://localhost:5000/tests/publication/add?name=New%20Publication
    2. Add Article: http://localhost:5000/tests/article/add?type=ReviewArticle&title=Test%20article%202018&note=My%20test%20note&publicationId=1
    3. Propose an article: http://localhost:5000/tests/proposal/add?type=ReviewArticle&title=Test proposal 1&note=Proposal%20note%201
    4. Accept the article proposal (NOTE: the article ID may differ on your system): http://localhost:5000/tests/accept/1?publicationId=2

Issues

  1. The last call is throwing the following exception:

    InvalidCastException: Unable to cast object of type
    'si.dezo.test.DotNetAudit.Models.Article' to type
    'si.dezo.test.DotNetAudit.Models.ArticleProposal'.
    
  2. I commented out a few lines of code in TestDbContext.cs and marked it as

    NOTE: the below is not working

Am I doing something wrong or is it a limitation or a bug of the library?

Is there a way around the issue?

damird
  • 73
  • 4

1 Answers1

1

The problem is that the library is supporting only one action for each Target type (audit type).

When you call .Map with an action like this:

.Map<Article, Audit_Article>((evt, entry, auditTbl) => { /*some action*/ })

It will store the action related to the type Audit_Article, but your next call:

.Map<ArticleProposal, Audit_Article>((item, auditTbl) => { /*overriding action*/ })

will override your previous action for any type that maps to Audit_Article.

So my initial recommendation is to use the common action via .AuditEntityAction<IAudit>. Is that causing you any issues?

I think it's possible to extend the library to allow mapping multiple types to the same target type with independent actions for each. I will take a look.

UPDATE

This has been implemented on Audit.EntityFramework version 13.2.0, you can now have multiple entities mapping to the same audit type with independent action for each.

thepirat000
  • 12,362
  • 4
  • 46
  • 72
  • 1
    I though the issue is caused by a limitation in the library, but I didn't dig into the lib itself as I'm not so fluent with C# yet. Also, I wasn't able to get the `.AuditEntryAction` working and can't remember right now what issue I faced. Anyway, I came up to a work-around that I'll push to GitHub and comment here later. The mentioned work-around solves my problem at the moment, so I can proceed with my work. Nevertheless, I'll try to get the `.AuditEntryAction` working as well at a later stage. Last I would vote for the improvement of the lib to support log to single table :) – damird Oct 31 '18 at 13:52
  • I've opened an [issue](https://github.com/thepirat000/Audit.NET/issues/175) for this and will work on the change. Regards – thepirat000 Oct 31 '18 at 16:37
  • 1
    This has been implemented on version 13.2.0, you can now have multiple entities mapping to the same audit type with independent action for each. [Sample code](https://github.com/thepirat000/Audit.NET/blob/master/test/Audit.EntityFramework.Core.UnitTest/EfCore21Tests.cs#L29) – thepirat000 Oct 31 '18 at 21:17
  • 1
    I implemented a work-around solution by using one-to-one table audit logging and aggregating multiple audit tables into a view which I mapped to a DbContext using `DbQuery` - the work-around is tagged `View_WorkAround`. Thanks @thepirat000, I'll check the update you mentioned as well. – damird Oct 31 '18 at 21:58