Home > Software engineering >  Returning DataTable or DataSet from EntityFramework
Returning DataTable or DataSet from EntityFramework

Time:12-20

I have a number of Functions in a Data Access Layer that are currently using ADO.Net, but I'm investigating how to rewrite these to use EntityFramework in stead.

Since most of these functions return DataTable objects, it would be nice to be able to keep returning DataTable (at least for a period). Let's say that one of the functions look like this:

public async Task<DataTable> GetGoblinsAsync(CancellationToken cancelToken)
{
    using (var conn = GetConnection())
    {
    await conn.OpenAsync(cancelToken).ConfigureAwait(false);
    var command =  new SqlCommand("select * from [SomeGoblinTable]", conn); 
    using (SqlDataReader reader = await command.ExecuteReaderAsync(cancelToken).ConfigureAwait(false))
    {
        DataTable dt = new DataTable();
        dt.Load(reader);
        return dt;
    }
    }
}

CodePudding user response:

To rewrite this function to use Entity Framework, you can start by adding a reference to the Entity Framework NuGet package and using the DbContext class to connect to your database.

Here's how you could rewrite the GetGoblinsAsync function using Entity Framework:

using (var context = new MyDbContext())
{
    // Use the DbSet<T> for the entity type you want to retrieve
    var goblins = context.Goblins.ToListAsync(cancelToken);
    return ToDataTable(goblins);
}

Note that this will return a list of entity objects instead of a DataTable. To convert the list of entities to a DataTable, you can use a helper function like this:

`public DataTable ToDataTable<T>(List<T> items)
{
    DataTable dataTable = new DataTable(typeof(T).Name);

    //Get all the properties
    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo prop in Props)
    {
        //Setting column names as Property names
        dataTable.Columns.Add(prop.Name);
    }
    foreach (T item in items)
    {
        var values = new object[Props.Length];
        for (int i = 0; i < Props.Length; i  )
        {
            //inserting property values to datatable rows
            values[i] = Props[i].GetValue(item, null);
        }
        dataTable.Rows.Add(values);
    }
    //put a breakpoint here and check datatable
    return dataTable;
}`

This will allow you to convert the list of entity objects to a DataTable and return it from the GetGoblinsAsync function as before.

You can then use Entity Framework to query and retrieve data from the database in your other functions as well. For example, you can use the Where method to filter the results, the Include method to eager-load related entities, and the AsNoTracking method to improve performance by disabling entity tracking.

I hope this helps! Let me know if you have any questions.

CodePudding user response:

Using FastMember (nuget) you can do:

public static class EnumerableExtensions
{
    public static DataTable ToDataTable<T>(this IEnumerable<T> source)
    {
        var dt = new DataTable();
        using (var reader = ObjectReader.Create(source))
            dt.Load(reader);
        return dt;
    }
}

CodePudding user response:

You can use EF Core on .NET Framework 4.7.2 and up with EF Core 3.1. Start by reading how EF works on the official site https://www.entityframeworktutorial.net/basics/how-entity-framework-works.aspx

Basically add EF Core NuGet packages you need in data layer:

Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

Build ApplicationDbContext

using Microsoft.EntityFrameworkCore;

namespace TestCoreApplication.Data
{
    public partial class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
        {
        }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }      

        //Add db sets here
        public virtual DbSet<Goblin> Goblins{ get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("ConnectionString");
                //Move the connection string to appSettings.json or to other safe places 
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //You have work here if you have specific model relations
            OnModelCreatingPartial(modelBuilder);
        }


    }
}

Add ApplicationDbContext to the dependency container in Program/StartUp

services.AddDbContext<ApplicationDbContext>(
                options => options.UseSqlServer("ConectionString"));
//Move the connection string to appSettings.json or to other safe places

Use it to return your Data as GataType you need

//call context in service
private readonly ApplicationDbContext context;
public YourService(ApplicationDbContext context)
{
   this.context = context;
}

public async Task<List<Goblin>> GetGoblinsAsync()
{
    //List of all goblins
    var goblins = await this.context.Goblins.ToListAsync();

    //List of goblins by where conditions
    var goblins = await this.context.Goblins.Where(x => x.Id == "id" && x.Name = "name").ToListAsync();

}
  • Related