question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] Json data using ef core

See original GitHub issue

First of all, I may be wrong, sorry in advance. I want to use web api audit and ef core audit. I’m using a customized “provider” as far as I can see from the examples. I learned that “web api audit” will not be used with “ef core audit” and I switched to “sql data provider”. I am currently using ef core by default in my project.

public class MyCustomDataProvider : AuditDataProvider
{
    private readonly SqlDataProvider _webApiEventsDataProvider;
    private readonly SqlDataProvider _efEventsDataProvider;

    public MyCustomDataProvider(Action<ISqlServerProviderConfigurator> webApiConfig,
        Action<ISqlServerProviderConfigurator> efConfig)
    {
        _webApiEventsDataProvider = new SqlDataProvider(webApiConfig);
        _efEventsDataProvider = new SqlDataProvider(efConfig);
    }

    public override object InsertEvent(AuditEvent auditEvent)
    {
        return GetDataProvider(auditEvent).InsertEvent(auditEvent);
    }

    public override async Task<object> InsertEventAsync(AuditEvent auditEvent)
    {
        return await GetDataProvider(auditEvent).InsertEventAsync(auditEvent);
    }

    private SqlDataProvider GetDataProvider(AuditEvent auditEvent)
    {
        return auditEvent switch
        {
            AuditEventWebApi _ => _webApiEventsDataProvider,
            AuditEventEntityFramework _ => _efEventsDataProvider,
            _ => throw new ArgumentException("Audit.Net provider is null")
        };
    }
}

The first question I want to ask now is;

Since I use ef core by default, does it make sense for me to use a different “provider” again? How to use web api audit with ef core audit?

 public static void UseSettingsAudit(this IApplicationBuilder app, IConfiguration configuration)
    {
        string connectionString = configuration.GetConnectionString("DefaultConnection");

        _ = Audit.Core.Configuration.Setup()
            .UseCustomProvider(new MyCustomDataProvider(api => api.ConnectionString(connectionString)
                    .Schema("dbo")
                    .TableName("MyAuditWebApi")
                    .IdColumnName("Id")
                    .JsonColumnName("AuditData")
                    .CustomColumn("AuditDate", _ => DateTime.Now),
                ef => ef.ConnectionString(connectionString)
                    .Schema("dbo")
                    .TableName("MyAuditEFCore")
                    .IdColumnName("Id")
                    .CustomColumn("TableName", auditEvent => auditEvent.GetEntityFrameworkEvent().Entries[0].Table)
                    .CustomColumn("TableId",
                        ev => Convert.ToInt32(ev.GetEntityFrameworkEvent().Entries[0].PrimaryKey.FirstOrDefault()
                            .Value))
                    .CustomColumn("UserName", auditEvent => "DOLDURULACAK")
                    .CustomColumn("AuditData", auditEvent =>
                    {
                        var entries = auditEvent.GetEntityFrameworkEvent().Entries[0];

                        object data = entries.Action is "Update" ? entries.Changes : entries.ColumnValues;

                        return JsonSerializer.Serialize(data, new JsonSerializerOptions
                        {
                            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                        });
                    })
                    .CustomColumn("Action", ev => ev.GetEntityFrameworkEvent().Entries[0].Action)
                    .CustomColumn("AuditDate", e => DateTime.Now)));
    }

I’m getting “connectionstring” again, transferring it to the provider or something, it didn’t make sense to me. I already use ef core by default.

my second question;

you’ve probably seen it. With .net 7, the json column feature came. As far as I understand from the documents, a json column query is created over the classes. to do this i need to create classes for my model. Of course, how do I query the dynamically saved data with constants, there is a little problem there.

https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew

By the way your libraries are very good. thank you for everything. I guess there is no problem with saving, there is a problem with queries, at least for me.

Issue Analytics

  • State:closed
  • Created 7 months ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
thepirat000commented, Mar 7, 2023

@mansurdegirmenci Note that the overload with the guard condition for Custom Columns in SqlServer data provider was added in version 20.2.0

1reaction
thepirat000commented, Mar 3, 2023

You can add a parameterless constructor to the entity classes (CustomJsonEntry, CustomJsonEntryChange) it shouldn’t be a problem. the custom constructors were only for making the configuration shorter.

For the DbContext constructor issue, I think you have some options:

  1. If it’s OK for you, you can just remove the .UseDbContext() call, so the same DbContext instance will be used to store the audits.

or

  1. You can use the overload .UseDbContext(Func<AuditEventEntityFramework, DbContext>) that let you create the DbContext instance for each event, for example using the HttpContextAccessor to get the DbContext from the service provider:
// in your startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DataListContext>(opt => opt...);
    services.AddHttpContextAccessor();
    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
{
    Audit.Core.Configuration.Setup()
        .UseCustomProvider(new MyCustomDataProvider(api => api
                ...,
            ef => ef
                .UseDbContext(_ => httpContextAccessor.HttpContext.RequestServices.GetService<DataListContext>())
                .DisposeDbContext()
                .AuditTypeExplicitMapper(...));
    // ...
}

or

  1. Store the DbContextOptions you get in the constructor of your DbContext, and use it to generate a new DbContext for the audit reusing the DbContextOptions.
public partial class DataListContext : AuditIdentityDbContext<AspNetUser, AspNetRole, int>
{ 
    private readonly DbContextOptions<MyContext> _options;

    public MyContext CreateAuditDbContext() => new MyContext(_options);

    public DataListContext(DbContextOptions<DataListContext> options) : base(options)
    {
        _options = options;
    }
}

// On your startup.cs, configure how to obtain the audit DbContext instance:
        .UseDbContext(ev => ((DataListContext)ev.GetEntityFrameworkEvent().GetDbContext()).CreateAuditDbContext())
        .DisposeDbContext()
        ...
Read more comments on GitHub >

github_iconTop Results From Across the Web

JSON Columns in Entity Framework Core
In Entity Framework (EF) Core, JSON columns can be used to store and query JSON data in a database. EF Core supports mapping...
Read more >
How to store JSON in an entity field with EF Core?
Instead you can use EF Core's HasConversion() method on the EntityTypeBuilder object to convert between your type and JSON.
Read more >
Getting Started: Entity Framework Core 7 JSON Support
This post will discuss the advantages of using JSON when data modeling, the benefits of storing JSON, and how to work with JSON...
Read more >
Deserialialize the json file & seed it in the sql server ...
There are two basic steps, First, create EF models using code first as explained in any tutorials. Next, you'll write custom initialization logic...
Read more >
Announcing Entity Framework Core 7 RC2: JSON Columns
EF Core 7.0 (EF7) adds support for mapping aggregate types to JSON documents stored in “JSON columns” of a relational database. This allows ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found