是否可以手动修改IQueryable表达式
本文关键字:修改 IQueryable 表达式 是否 | 更新日期: 2023-09-27 18:21:50
我很确定我知道答案是否定的,但作为最后的尝试,我想我应该在这里问这个问题。
我首先使用EF代码以通常的方式查询表
_context.Set<Foo>().Where(f => f.Bar == 999);
它创建了以下表达式(我刚刚写了这个,所以它可能是错误的)。
{SELECT
[Extent1].[Test] AS [Test],
[Extent1].[Test2] AS [Test2],
FROM [dbo].[Foo] AS [Extent1]
WHERE 19 = [Extent1].[Bar]}
现在,是否可以手动修改此查询以将表名更改为Foo10?(可能不是)
如果做不到这一点,有人知道我可以先在代码中"延迟绑定"表名的方法吗?
你可能想知道"为什么是肮脏的黑客?"和往常一样,这是一个数据库的遗留问题,它有一些设计问题,无法更改。
提前谢谢。
Ps。我知道我可以使用Database.SqlQuery
,但我宁愿不使用。
为什么不在模型上使用TPT继承?
类似于@Krizz的回答,但您避免使用动态LINQ。
使用您的评论:
如果一个特定参数的值为1,则在Foo1中查找,如果它在Foo2中查找2,依此类推
所以,你可以这样做:
var query = ctx
.Foos
.OfMyType(value)
.Where(f => f.Bar == 999) // f.Bar is on the base/abstract entity.
.ToList();
其中OfMyType
是IQueryable<T>
:上的自定义扩展方法
public static IQueryable<T> OfMyType<T>(this IQueryable<T> source, string value)
{
switch (value)
{
case "1":
return source.OfType<Foo1>();
case "2":
return source.OfType<Foo2>();
// etc, etc
}
}
大多数(如果不是全部的话)属性都将在抽象的"Foo"实体上,并且您为每个表创建派生实体,每个表都有自己的支持表。
这样,"消耗"代码(例如进行查询的代码)就不必关心不同的表/Foo,它们只需将"神奇的值"传递到您的存储库(希望是您正在使用的存储库),然后您就可以无声地切换到您想要的表。
这样行吗?
假设您有合理数量的表,我会将它们全部添加到模型中,并创建一个所有类都将实现的公共接口,然后选择合适的模型并使用Dynamic Linq进行查询。
我不确定这是否有效,没有检查过,也没有使用";EF码优先";,但这是我会尝试的东西:
假设您的表Foo
有字段-Bar
、Pub
、X
,并且让X
是相应表所依赖的字段?
然后,我将定义接口:
interface IFoo
{
int Bar { get; set; }
string Pub { get; set; }
int X { get; set; }
}
然后每个表在模型中都有自己的类:
[Table("Foo1")]
class Foo1 : IFoo
{
public int Bar { get; set; }
public string Pub { get; set; }
public int X { get; set; }
}
[Table("Foo2")]
class Foo2 : IFoo
{
public int Bar { get; set; }
public string Pub { get; set; }
public int X { get; set; }
}
然后你可以像下面这样过滤它们:
IQueryable GetAdequateFoo(int X)
{
switch (X) // you could use reflection here to dynamically call the given Set<Foo#>()
{
case 1:
return _context.Set<Foo1>();
case 2:
return _context.Set<Foo2>();
default:
return null;
}
}
IFoo GetFooByBarAndX(int bar, int X)
{
IQueryable context = GetAdequateFoo(X);
return context.Where("it.Bar == @0", bar).Cast<IFoo>();
}
以下是如何使用新的/修改过的表达式(撰写本文时为EF core 5.0)创建新的IQueryable。
var expression = query.Expression;
//modify your expression usually by building a new one or rebuilding using an ExpressionVisitor
var newQuery = query.Provider.CreateQuery(expression);
注意:我在IQueryable上搜索编辑表达式,这是第一个出现的问题,但细节集中在一个非常具体的用例上,而更普遍的问题还没有得到回答。。。