zzzprojects / EntityFramework-Plus

Entity Framework Plus extends your DbContext with must-haves features: Include Filter, Auditing, Caching, Query Future, Batch Delete, Batch Update, and more
https://entityframework-plus.net/
MIT License
2.27k stars 318 forks source link

AuditId property in AuditEntry DB Table, but not in Model #790

Closed VieruTudor closed 9 months ago

VieruTudor commented 10 months ago

Description

I tried to extend and save the Audit entity in the Database. I created a class that inherits from that, added a custom property and migrated, seems good, it gets saved in DB whenever I create and Audit. Moreover, the AuditEntry tabel has received a new column called AuditId, which I have not added and is populated with the correct AuditId. However, I cannot access that value with EntityFramework in any way shape or form.

Is this something intended and I'm missing something?

Code Example

The extended audit class

public class AuditLog : Z.EntityFramework.Plus.Audit
{
    public int Id { get; set; }

    public DateTime CreatedDate { get; set; }
}

The DbContext configuration

public DbSet<AuditLog> AuditLogs { get; set; }
public DbSet<AuditEntry> AuditLogEntries { get; set; }
public DbSet<AuditEntryProperty> AuditEntryProperties { get; set; }
...
mb.Entity<AuditLog>().ToTable("AuditLogs", "CMS")
        .Property(x => x.Id).IsRequired();

mb.Entity<AuditEntry>().ToTable("AuditLogEntries", "CMS");

mb.Entity<AuditEntryProperty>().ToTable("AuditEntryProperties", "CMS");

What is generated in the DB: image

As I've said, the "AuditLogId" value gets populated correctly, but I'm not able to access it. I presume it was added because of AuditEntry.Parent navigation property, but that class doesn't have an Id either.

JonathanMagnan commented 10 months ago

Hello @VieruTudor ,

The Audit / AuditLog class was not initially intended to be saved in the database.

I believe it's the first time we have this request. Our library is probably missing a factory to be able to create the AuditLog class as we allow to do with AuditEntry and AuditEntryProperty. For example:

AuditManager.DefaultConfiguration
    .AuditEntryFactory = args => 
    new CustomAuditEntry() { Time_CustomAuditEntry = DateTime.Now  };

Do you really want to save this AuditLog row? You already have the CreatedDate in the AuditEntry entity type. However, I understand that you want to know all AuditEntry belongs to a specific AuditLog.

Let me know if that's really something you want and we will look at it if that's the case.

Best Regards,

Jon

VieruTudor commented 10 months ago

Thanks for your prompt response, Jon!

I'd really need the Audit/AuditLog row saved, since there might be the following (quite common) case. Say I have the following entity:

public class UserDetails
{
    /// whatever properties
    public List<Address> Adresses { get; set; }
}

When I want to update the UserDetails, and say I would also want to update on of the Addresses in the List, they are updated in the same SaveChanges call, since it's a navigation property. Therefore, these belong to the same audit and should be identified as such.

To give more context on why I need this, I'm implementing an audit & restore system that based on AuditEntries and AuditEntryProperties, would be able to revert certain changes done to an entity that is being audited, that's why I need them to be grouped in some sort. However, I believe the case for just seeing the entities updated in the same Audit is quite common, and since the library already has a navigation property between Audit (.Entries) and AuditEntry (.Parent), I believe an Id should have existed from the first place.

JonathanMagnan commented 10 months ago

Hello @VieruTudor ,

Thank you for the additional context. I will check over the weekend to see what could be possible.

Best Regards,

Jon

JonathanMagnan commented 10 months ago

Hello @VieruTudor ,

Here is a working example from what I understand of your request: https://dotnetfiddle.net/yVqLlQ

You will notice at least 3 big differences:

Let me know if that example solves your issue or not.

Best Regards,

Jon