0

I'm trying to create a system that the user can choose the table to get data from. It's like there's a dropdownlist of table names and then for example the user chooses the table Company, in the code it will be like _context.Company.Tolist() if the user chooses Department, it will be like _context.Department.Tolist()

Is there a way that I can make that part a variable? like _context.[variableName].Tolist()? Or is there any other way to do this?

  • Please check out this thread: https://stackoverflow.com/questions/26305737/how-do-i-select-correct-dbset-in-dbcontext-based-on-table-name – Peter Csala Apr 17 '20 at 08:42

2 Answers2

0

Well, there's Set<T> you can use to generically access a DbSet, i.e. instead of _context.Company, you can use _context.Set<Company>(). However, where things get sticky is in allowing this to be specified dynamically.

Regardless of how you handle it, you're going to somehow have to "convert" a string into some entity type. For example, even if you use the actual class name as the option values in your select list. You're going to get "Company" back, not Company, the class. You could use reflection to try to find the actual type via the string, but that's not going to be be trivial, especially if these classes could be in different namespaces, or if the class name is ever repeated (i.e. the same class name exists in multiple namespaces). Even then, you'd also have to use reflection to access the set generically, which is also kind of a pain.

Long and short, unless there's a true need for this to be truly dynamic, or you're dealing some number of tables where it would be infeasible to not handle it dynamically, then you should just switch on the value and handle it somewhat statically. For example, if all you have is Company and Department, then it would be more clear, faster, and less error-prone to just check what the user selected and manually call the right DbSet.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
0

I think @Peter has given you an good idea.

You can extend the custom Set method, below I created a complete case, you can refer to:

Controller:

public class ChangeListController : Controller
{
    private readonly MyDbContext _context;
    public ChangeListController(MyDbContext context)
    {
        _context = context;
    }
    public IActionResult Index()
    {
        return View();
    }
    public IActionResult GetDifferentTable(string table)
    {
        var type = Assembly.GetExecutingAssembly()
    .GetTypes()
    .FirstOrDefault(t => t.Name == table);
        if(type != null)
        { 
            var tbList= _context.Set(type).ToList();
        } 
        return View("Index");
    }

}
public static class MyExtensions
{
    public static IQueryable<object> Set(this DbContext _context, Type t)
    {
        return (IQueryable<object>)_context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
    }
}

Index:

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Index</h1>
@section Scripts{
    <script>
        function doIt(item, baseUrl) {  
            $.ajax({
                url: baseUrl,
                type: 'POST',
                data: { "table": item.value },
                dataType: 'json',
            });
        }
    </script>

}
<select class="custom-select" onchange="doIt(this,'@Url.Action("GetDifferentTable", "ChangeList")')">
    <option value="Teachers"> Teachers</option>
    <option value="Term">Term</option>
    <option value="Product">Product</option>
    <option value="Student">Student</option>
</select>

Here is the debug result:

enter image description here

LouraQ
  • 6,443
  • 2
  • 6
  • 16