我很确定我知道答案是否定的,但作为最后的尝试,我想我会在这里问这个问题。
我首先使用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? (可能不是)
如果不这样做,是否有人知道我可以在代码中“晚点绑定”表名的方式?
你可能想知道“为什么肮脏的黑客?”像往常一样,这是一个遗留问题,数据库存在一些设计问题,无法更改。
提前致谢。
聚苯乙烯。我知道我可以使用Database.SqlQuery
但不愿意。
答案 0 :(得分:2)
为什么不在模型上使用TPT继承?
与@ Krizz的答案类似,但您避免使用动态LINQ。
使用您的评论:
如果特定参数的值为1,请查看Foo1,如果它的2看起来在Foo2中,依此类推
所以,你可以这样做:
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,他们只是将“魔术值”传递给你的存储库(希望你使用它),然后就可以了静静地切换到你想要的桌子。
那会有用吗?
答案 1 :(得分:1)
假设您有合理数量的表,我会将它们全部添加到模型中并创建一个所有类将实现的公共接口,然后选择适当的模型并使用Dynamic Linq进行查询。
我不确定这是否有效,没有检查过,并且没有使用过“EF代码优先”,但我会尝试这样做:
假设您的表格Foo
包含字段 - Bar
,Pub
,X
,让X
成为相应表所依赖的字段上?
然后,我会定义interface:
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>();
}
这只是未经过测试的建议并且是从头上写的,如果我错了,请不要投票,并指出任何潜在的问题。
答案 2 :(得分:0)
这不是我建议的,但是你可以通过ToString()查询将SQL语句放到变量中然后用字符串替换表名。然后SQL执行那个SQL?
臭臭和黑客但可能吗?
答案 3 :(得分:-1)
以下是如何使用新的/修改过的表达式(在撰写本文时为 EF 核心 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 上编辑表达式,这是第一个出现的问题,但细节随后集中在一个非常具体的用例上,更一般的问题尚未得到解答......
>