Database Table Export to CSV using EntityFramework DbContext .NET 6
I have been tasked to create a Blazor ASP.NET Core application that will export each table from an MS SQL Server database into it's own .csv
file. I have extracted the DbSets
from the DbContext
properties into a generic list, but when I attempt to cast the generic objects to their DbSet
class I get the following error:
An unhandled exception occurred while processing the request. MissingMethodException: Constructor on type 'Microsoft.EntityFrameworkCore.DbSet`1[[DatabaseTableExport.Data.LoginDbModels.AccountPasswordHistory, DatabaseTableExport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found. System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture)
How do I fix this error, or is there a better way to be extracting the DbSets
from the DbContext
?
using DatabaseTableExport.Data;
using DatabaseTableExport.Data.LoginDbModels;
using Microsoft.AspNetCore.Components;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace DatabaseTableExport.Pages
{
public partial class Index : ComponentBase
{
[Inject]
private LoginDbContext LoginDbContext { get; set; }
[Inject]
private ApplicationDbContext ApplicationDbContext { get; set; }
protected override void OnInitialized()
{
List<DbSet<object>> dbSets = GetDbSets(LoginDbContext);
// iterate through each DbSet instance
foreach (var dbSet in dbSets)
{
// export to csv here
}
}
private static List<DbSet<object>> GetDbSets(DbContext loginDbContext)
{
// Retrieve all the DbSet properties declared on the context class.
var dbSetProperties = loginDbContext.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
.ToList();
// Iterate over each DbSet property and add it to the list of dbsets.
var dbSets = new List<DbSet<object>>();
foreach (var property in dbSetProperties)
{
// If the type of the DbSet is null, skip it.
if (property.PropertyType.GenericTypeArguments.Length <= 0)
{
continue;
}
// Get the generic type arguments and create a corresponding DbSet instance.
var dbsetGenericType = property.PropertyType.GenericTypeArguments[0];
var convertedDbSet = Activator.CreateInstance(typeof(DbSet<>).MakeGenericType(dbsetGenericType), property.GetValue(loginDbContext));
dbSets.Add((DbSet<object>)convertedDbSet);
}
// Return the list of DbSet objects.
return dbSets;
}
}
}