Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态LINQ IQueryable(在运行时生成表达式)_C#_Linq_Dynamic Linq - Fatal编程技术网

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个键的对象,等等。