C# 动态LINQ IQueryable(在运行时生成表达式)
我有以下疑问C# 动态LINQ IQueryable(在运行时生成表达式),c#,linq,dynamic-linq,C#,Linq,Dynamic Linq,我有以下疑问 query.Join( relationEntity, entity => new { Prop1 = EF.Property<object>(entity, "Id"), Prop2 = Ef.Property...}, relation => new { Prop1 = EF.Property<object>(relation, "EntityId"), Prop2 = EF.Property... }, (E
query.Join(
relationEntity,
entity => new { Prop1 = EF.Property<object>(entity, "Id"), Prop2 = Ef.Property...},
relation => new { Prop1 = EF.Property<object>(relation, "EntityId"), Prop2 = EF.Property... },
(Entity, Relation) => new { Entity, Relation })
query.Join(
关系实体,
entity=>new{Prop1=EF.Property(entity,“Id”),Prop2=EF.Property…},
relation=>new{Prop1=EF.Property(relation,“EntityId”),Prop2=EF.Property…},
(实体,关系)=>新的{实体,关系})
我需要在运行时生成密钥。如何才能做到这一点?我已经尝试在运行时构建一个表达式,但它看起来像是从字面上获取接收的值,因此如果我在那里调用一个方法,它将被转换为该方法名,而不是结果
我用atm测试的方法是:
private static object MyMethod(object entity, string name)
=> new { Id = EF.Property<object>(entity, name) };
query.Join(
relationEntity,
entity => MyMethod(entity, "Id"),
relation => MyMethod(relation, "EntityId"),
(Entity, Relation) => new { Entity, Relation })
私有静态对象MyMethod(对象实体、字符串名称)
=>新的{Id=EF.Property(实体,名称)};
查询.加入(
关系实体,
实体=>MyMethod(实体,“Id”),
关系=>MyMethod(关系,“EntityId”),
(实体,关系)=>新的{实体,关系})
要使MyMethod成为一个表达式,您必须这样处理它
private static Expression<Func<T, object>> MyMethod<T>(string name) =>
(T entity) => new { Id = EF.Property<object>(entity, name) };
query.Join(
relationEntity,
MyMethod<entityType>("Id"),
MyMethod<relationType>("EntityId"),
(Entity, Relation) => new { Entity, Relation })
私有静态表达式MyMethod(字符串名称)=>
(T实体)=>新的{Id=EF.Property(实体,名称)};
查询.加入(
关系实体,
MyMethod(“Id”),
MyMethod(“EntityId”),
(实体,关系)=>新的{实体,关系})
该方法必须返回一个表达式,而不是任何计算结果
但MyMethod越复杂,就越不可能将其转换为SQL
这里更多的是让代码更短、更可读。那里还没有什么动态
这样的选择不是问题,因为此选择是在创建SQL之前执行的
private static Expression<Func<T, object>> MyMethod<T>(string name)
{
if (case 1)
return (T entity) => new { Id = EF.Property<object>(entity, name) };
if (case 2)
return (T entity) => new { Id = EF.Property<object>(entity, name), Id2 = ... something else }
}
私有静态表达式MyMethod(字符串名称)
{
如果(案例1)
return(T entity)=>new{Id=EF.Property(entity,name)};
如果(案例2)
return(T entity)=>new{Id=EF.Property(entity,name),Id2=…something other}
}
您应该在问题中输入您尝试使用表达式的代码。如果在表达式中放入Method.Call,它当然会在表达式运行时执行。如果希望在编译时计算,则必须创建一个常量表达式。比如新的恒常表达式(math.sqrt(2))。这将在编译时调用sqrt,或者如果在创建表达式时包含变量。@Holger感谢您提供的信息,我有两个问题不知道如何解决,第一个问题是基于属性名列表动态构建新的{Prop=EF..,Prop2=EF…}。第二个是你描述的。(我对问题进行了编辑,以显示我使用atm的方法)我测试了很多不同的方法,甚至都记不清了:D您的代码中仍然没有出现单词表达式。什么不起作用?(肯定在LINQtoSQL中不起作用,这就是问题所在吗?)。表达式无法在运行时动态生成类型。但是,使用已知类型很容易解决这个问题。是的,LINQtoSQL就是这样。我正在使用EFCore 3.1。但是属性是阴影属性,这就是为什么需要Ef.属性…那么这里的变量是什么?为什么您不仅仅是entity=>entity.ID?实体必须有一个已知的类型,为什么要这么多地使用对象?如果您在“对象”上加入,则无法生成SQL查询。SQL无法比较对象。查询和关系实体的类型是什么?哇,非常感谢你,只是为了确定一下。第二部分没有办法让它变为动态的,对吗?第二部分是关于可变数量的参数,实际上它应该在没有元组的情况下工作。但是现在函数只有一个name参数,对于一个ID,不知道如何处理更多的复合键部分。这与其说是解决方案,不如说是一种策略。您必须以某种方式确保,对MyMethod的2个调用将返回相同类型的对象,而不是一个具有2个键的对象,或者一个具有5个键的对象,等等。