1

I made this function that retrieves all the data.

public static List<Volunteer> GetAllVolunteers()
{
    using (VolunteerPlacementSystemDBEntities1 db = new VolunteerPlacementSystemDBEntities1())
    {
        return db.Volunteers.**Include(v => v.roleForVolunteers).Include(v => v.VolunteerOffers)
                         .Include("VolunteerOffers.daysForAVolunteers")**.ToList();
    }
}

And I have this generic function that retrieves DBSet T.

public static List<T> GetDbSet<T>() where T : class
{
    using (VolunteerPlacementSystemDBEntities1 db = new VolunteerPlacementSystemDBEntities1())
    {
        return db.GetDbSet<T>().ToList();
    }
}

Can I make a generic function that will retrieve all the data that connect to one DBSet T?

Thanks in advance.

Etheraex
  • 508
  • 6
  • 17
N.A
  • 68
  • 8
  • Does this answer your question? [Entity Framework - Include / Reference / Collection](https://stackoverflow.com/questions/18072243/entity-framework-include-reference-collection) – Etheraex May 24 '22 at 10:57
  • I did not quite understand how to adapt it to me – N.A May 24 '22 at 11:14
  • You need to use Reflection for extract all your Property from T that can include. – Den May 24 '22 at 11:35

3 Answers3

1

Get DbSet for the T Entity Class Type from context as DbSet<T> or IQueryable<T>.

On this IQueryable<T> object can perform multiple operations like Where(), Include(), orderBy() etc with help of namespace System.Linq.

  • With Include() method, pass on required included properties.

  • For Parallel processing use TPL from System.Threading.Tasks

Try this:

public static List<T> GetDbSet<T>(string[] includeProperties) where T : class
{
    using (VolunteerPlacementSystemDBEntities1 db = new VolunteerPlacementSystemDBEntities1())
    {
        IQueryable<T> query = db.Set<T>();

        Parallel.ForEach(inlcudeProperties, includeProperty => {
           query.Include(includeProperty);
        });

        return query.ToList();
    }
}
Nayan
  • 471
  • 2
  • 9
  • I'm grateful Can you maybe tell me how I also give a Include of two levels? i made this array for example: public static string[] include { get; set; } = { "roleForVolunteers", "VolunteerOffers", " VolunteerOffers.daysForAVolunteers " }; and this: VolunteerOffers.daysForAVolunteers gave me an error – N.A May 24 '22 at 11:50
  • have VolunteerOffers be virtual property in T class and exclude that item from list. So you can be able to access that daysForVolunteers from virtual property – Nayan May 24 '22 at 11:57
  • VolunteerOffers is virtual already – N.A May 24 '22 at 12:03
  • public static string[] include { get; set; } = [ "roleForVolunteers", "VolunteerOffers" ]; – Nayan May 24 '22 at 12:06
  • 2
    If you need this, you can try change string[] parameter with `IIncludableQueryable> includesFunc` and then `includesFunc(query)` – Den May 24 '22 at 12:11
  • 1
    thanks, but i don't understand on what the error – N.A May 24 '22 at 13:05
  • 1
    System.InvalidOperationException: 'The context cannot be used while the model is being created.... – N.A May 24 '22 at 13:09
  • 1
    Add MultipleActiveResultSets=true in connection string. – Nayan May 24 '22 at 13:12
0

Some month ago i try to do somthing like that, but i have tableName. I leave you some detail, that you can adapt

You extract form context all your table and select only the ClrType corrispond with your T type.

var selectedTable = contextDb.Model
            .GetEntityTypes()
            .Select(x => new TableSpecification // Custom class
            {
                TableName = x.GetTableName(),
                ClrType = x.ClrType,
                JoinTable = x.GetForeignKeys(),
                JoinTableProp = x.GetForeignKeyProperties(),
                NavigationProp = x.GetNavigations(),
                ColumnsTable = null
            })
           .Where(// where ClrType)
           .Distinct()
           .FirstOrDefault();

This is my custom class

using Microsoft.EntityFrameworkCore.Metadata;

using System;
using System.Collections.Generic;

namespace Seac.CRM.DbInfrastructure.Model.Context;

public class TableSpecification
{
    public string TableName { get; init; }
    public Type ClrType { get; init; }
    public IEnumerable<IForeignKey> JoinTable { get; init; }
    public IEnumerable<IProperty> JoinTableProp { get; init; }
    public IEnumerable<INavigation> NavigationProp { get; init; }
    public IEnumerable<IProperty> ColumnsTable { get; init; }
}

then you can extract all your reference property

var joinLookup = selectedTable.JoinTable.GetLookupForeignKey();

foreach (var lookup in joinLookup)
   queryable = queryable.Include(lookup.PrincipalEntityType.Name.Split(".").Last());

I wish that can help you.

*** EDIT

If you need a custom include of T you can use IIncludableQueryable<T, object>>

public static List<T> GetDbSet<T>(IIncludableQueryable<T, object>> include = null) where T : class
{
    using (VolunteerPlacementSystemDBEntities1 db = new VolunteerPlacementSystemDBEntities1())
    {
        IQueryable<T> query = db.Set<T>();

        if (includesFunc is not null)
            query = includesFunc(query);

        return query.ToList();
    }
}
Den
  • 650
  • 6
  • 15
0

Thanks to everyone who tried to help me. This is the solution that worked for me.

  public static List<T> GetDbSetWithIncludes<T>(string[] includes) where T : class
    {
        using (VolunteerPlacementSystemDBEntities1 db = new VolunteerPlacementSystemDBEntities1())
        {
            db.Configuration.LazyLoadingEnabled = false;
            return IncludeMultiple<T>(db.GetDbSet<T>(), includes).ToList();
        }
    }


 public static IQueryable<T> IncludeMultiple<T>(IQueryable<T> query, string[] includes)where T : class
        {
            if (includes != null)
            {
                query = includes.Aggregate(query, (current, include) =>
                current.Include(include));
            }
            return query;
        }
N.A
  • 68
  • 8