在LINQ查询中动态设置表名

zqry0prt  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(169)

I am working on data warehouse application and we have 4 tables where schema is identical. Only difference between those tables is just Table Name.
Table Example:

  • ps_Contractor
  • ps_Employee
  • ps_Union
  • ps_NonUnion

Schema

  • id
  • hourly
  • benefit
  • total

Now i need to generate 4 reports based on these tables. Instead of writing 4 separate LINQ queries i would like to write single query where i can pass the table name dynamically.
The question How do i pass the table name dynamically in following LINQ query ?

var data = ( from q in _dbcontext.ps_Contractor 
join _l in _dbcontext.log on q.id equals l.tablelogid 
where q.hourly = 8
select new{
 hourly=q.hourly,
 benefit=q.benefit,
 total=q.total,
 log = l.message
}.ToList();

I have looked at all similar questions suggested by stack overflow. I do not want to use ExecuteStoreQuery.
what options do i have ?

wribegjk

wribegjk1#

如果所有表都有相同的列,那么我将从这些表中提取一个interface,并创建partial entity classes来实现该接口,最后使用该接口进行查询。
例如:

//entities
public partial class ps_Contractor: ICommonInterface{}
public partial class Table2 : ICommonInterface{}

在search方法中,我会传递IEnumerable<ICommonInterface>IQueryable<ICommonInterface>,并在其上应用查询.您所需要做得只是将不同得表传递给该search方法.或者您甚至可以有ICommonInterface类型得泛型类,并使用该类来执行查询.

public void Example(IQueryable<ICommonInterface>dataSource)
{
var data = ( from q in dataSource 
join _l in _dbcontext.log on q.id equals l.tablelogid 
where q.hourly = 8
select new{
 hourly=q.hourly,
 benefit=q.benefit,
 total=q.total,
 log = l.message
}.ToList();
}

Example(_dbcontext.ps_Contractor.AsQueryable())

这只是我现在测试的一个示例:

public class Repository
{
    private List<string> GetData(IQueryable<IContractor> data)
    {
        return (from d in data select d.Name).ToList();
    }

    public List<string> GetFullTime()
    {
        using (var context = new TestDbEntities())
        {
            return GetData(context.FTContractors.AsQueryable());
        }
    }

    public List<string> GetPartTime()
    {
        using (var context = new TestDbEntities())
        {
            return GetData(context.PTContractors.AsQueryable());
        }
    }
}

实体:

public interface IContractor
    {
        int Id { get; set; }
        string Name { get; set; }
    }

    public partial class FTContractor : IContractor
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
public partial class PTContractor : IContractor
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

测试项目:

[TestMethod]
        public void Temp()
        {
            var tester = new Repository();

            var ft = tester.GetFullTime();
            var pt = tester.GetPartTime();

             Assert.AreEqual(3, ft.Count);
             Assert.AreEqual(4, pt.Count);
        }

在数据库中,有两个仅包含IdName列的表

8yoxcaq7

8yoxcaq72#

EF Core不再有非泛型的.set方法,但这个扩展类使使用动态Linq基于字符串查询表变得容易

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

    public static IQueryable<Object> Set(this DbContext _context, String table)
    {
        Type TableType = _context.GetType().Assembly.GetExportedTypes().FirstOrDefault(t => t.Name == table);
        IQueryable<Object> ObjectContext = _context.Set(TableTypeDictionary[table]);
        return ObjectContext;
    }
}

}
使用方法:

IQueryable<Object> query = db.Set("TableName");
// Filter against "query" variable below...
List<Object> result = query.ToList();
// or use further dynamic Linq
IQueryable<Object> query = db.Set("TableName").Where("t => t.TableFilter == \"MyFilter\"");
jm81lzqq

jm81lzqq3#

下面是一种执行动态函数的方法,该函数接受DbSet<T>(要作为参数传递的数据库类的类型)和特定表达式,以便在该表上构建查询:

private IQueryable<T> BuildQueriedCollection<T>(Expression<Func<T, bool>> exp, DbSet<T> dbTable) where T : class
{
    var appliedQueryCollection = dbTable.AsExpandable().Where(exp);
    return appliedQueryCollection;
}

你可以这样调用这个函数

Expression<Func<MyClass, bool>> myExp = myList => myList... // some condition...;
var dbset = dbContext.MyTable;
var query = BuildQueriedCollection(myExp, dbset);

相关问题