在LINQ查询中动态设置表名
本文关键字:设置 动态 LINQ 查询 | 更新日期: 2023-09-27 18:26:08
我正在开发数据仓库应用程序,我们有4个表的模式是相同的。这些表之间唯一的区别就是表名。
表示例:
- ps_承包商
- ps_雇员
- ps_Union
- ps_NonUnion
架构
- id
- 每小时
- 利益
- 合计
现在我需要根据这些表生成4个报告。我不想写4个单独的LINQ查询,而是想写一个可以动态传递表名的查询。
问题是如何在下面的LINQ查询中动态传递表名?
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();
我已经研究了堆栈溢出提出的所有类似问题。我不想使用ExecuteStoreQuery。
我有什么选择?
如果所有表都有相同的列,那么我会从这些表中提取一个interface
并创建partial entity classes
来实现该接口,最后使用该接口进行查询。
例如:
//entities
public partial class ps_Contractor: ICommonInterface{}
public partial class Table2 : ICommonInterface{}
在搜索方法中,我会传递CCD_ 3或CCD_。您所需要做的就是将不同的表传递给该搜索方法。或者,您甚至可以拥有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);
}
在数据库中,有两个表只包含Id
和Name
列
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'"");
以下是一种执行动态函数的方法,该函数接受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);