“带有语句主体的 lambda 表达式无法转换为表达式树”

发布于 2024-10-20 05:49:33 字数 384 浏览 3 评论 0原文

我正在使用 EntityFramework,在尝试编译以下代码时收到错误A lambda expression with a statements body cannot be conversion to an expression tree

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();

我不'不知道错误意味着什么,最重要的是如何修复它。有什么帮助吗?

I'm using the EntityFramework, I get the error A lambda expression with a statement body cannot be converted to an expression tree when trying to compile the following code:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();

I don't know what the error means and most of all how to fix it. Any help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

于我来说 2024-10-27 05:49:33

objects 是 Linq-To-SQL 数据库上下文吗?在这种情况下,您只能在 => 右侧使用简单表达式。操作员。原因是,这些表达式不会被执行,而是被转换为 SQL 以针对数据库执行。
试试这个

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();

Is objects a Linq-To-SQL database context? In which case, you can only use simple expressions to the right of the => operator. The reason is, these expressions are not executed, but are converted to SQL to be executed against the database.
Try this

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();
清风夜微凉 2024-10-27 05:49:33

您可以在 IEnumerable 集合的 lba 表达式中使用语句主体。
试试这个:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();

注意:
使用此方法时请仔细考虑,因为这样,您将在应用程序的内存中获得所有查询结果,这可能会对其余代码产生不必要的副作用。

You can use statement body in lamba expression for IEnumerable collections.
try this one:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();

Notice:
Think carefully when using this method, because this way, you will have all query results in the application's memory, that may have unwanted side effects on the rest of your code.

骄兵必败 2024-10-27 05:49:33

这意味着您不能在 lambda 表达式需要转换为表达式树的地方(例如使用 linq2sql 时的情况)使用带有“语句主体”的 lambda 表达式(即使用大括号的 lambda 表达式) 。

It means that you can't use lambda expressions with a "statement body" (i.e. lambda expressions which use curly braces) in places where the lambda expression needs to be converted to an expression tree (which is for example the case when using linq2sql).

墟烟 2024-10-27 05:49:33

在不了解更多关于您正在做什么的情况下(Linq2Objects、Linq2Entities、Linq2Sql?),这应该可以使其工作:

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();

Without knowing more about what you are doing (Linq2Objects, Linq2Entities, Linq2Sql?), this should make it work:

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();
北方的巷 2024-10-27 05:49:33

LINQ to SQL 返回对象正在实现 IQueryable 接口。因此,对于 Select 方法谓词参数,您应该只提供不带主体的单个 lambda 表达式。

这是因为 LINQ for SQL 代码不是在程序内部执行,而是在远程端(如 SQL Server 或其他服务器)执行。这种延迟加载执行类型是通过实现 IQueryable 来实现的,其中它的期望委托被包装在如下所示的 Expression 类型类中。

Expression<Func<TParam,TResult>>

表达式树不支持带有主体的 lambda 表达式,它只支持单行 lambda 表达式,例如 var id = cols.Select( col => col.id );

因此,如果您尝试以下代码,则不会'有效。

Expression<Func<int,int>> function = x => {
    return x * 2;
}

以下将按预期工作。

Expression<Func<int,int>> function = x => x * 2;

The LINQ to SQL return object were implementing IQueryable interface. So for Select method predicate parameter you should only supply single lambda expression without body.

This is because LINQ for SQL code is not execute inside program rather than on remote side like SQL server or others. This lazy loading execution type were achieve by implementing IQueryable where its expect delegate is being wrapped in Expression type class like below.

Expression<Func<TParam,TResult>>

Expression tree do not support lambda expression with body and its only support single line lambda expression like var id = cols.Select( col => col.id );

So if you try the following code won't works.

Expression<Func<int,int>> function = x => {
    return x * 2;
}

The following will works as per expected.

Expression<Func<int,int>> function = x => x * 2;
耳钉梦 2024-10-27 05:49:33

晚了 9 年,但是解决问题的方法不同(没有人提到过?):

语句主体可以与 Func<> 配合使用,但无法与 配合使用表达式>IQueryable.Select 需要一个Expression<>,因为它们可以为实体框架进行转换 - Func<> 不能。

因此,您要么使用 AsEnumerable 并开始处理内存中的数据(不推荐,如果不是真的必要的话),或者继续使用推荐的 IQueryable
有一种叫做linq query的东西,它使一些事情变得更容易:

IQueryable<Obj> result = from o in objects
                         let someLocalVar = o.someVar
                         select new Obj
                         {
                           Var1 = someLocalVar,
                           Var2 = o.var2
                         };

使用let,您可以定义一个变量并在select(或select)中使用它>where,...) - 并且您继续使用 IQueryable 直到您真正需要执行并获取对象。

之后您可以 Obj[] myArray = result.ToArray()

9 years too late to the party, but a different approach to your problem (that nobody has mentioned?):

The statement-body works fine with Func<> but won't work with Expression<Func<>>. IQueryable.Select wants an Expression<>, because they can be translated for Entity Framework - Func<> can not.

So you either use the AsEnumerable and start working with the data in memory (not recommended, if not really neccessary) or you keep working with the IQueryable<> which is recommended.
There is something called linq query which makes some things easier:

IQueryable<Obj> result = from o in objects
                         let someLocalVar = o.someVar
                         select new Obj
                         {
                           Var1 = someLocalVar,
                           Var2 = o.var2
                         };

with let you can define a variable and use it in the select (or where,...) - and you keep working with the IQueryable until you really need to execute and get the objects.

Afterwards you can Obj[] myArray = result.ToArray()

你爱我像她 2024-10-27 05:49:33

使用 select 的重载:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();

Use this overload of select:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();
黯淡〆 2024-10-27 05:49:33

这意味着 TDelegate 类型的 Lambda 表达式包含 ([parameters]) => { some code }; 无法转换为 Expression。这是规则。

简化您的查询。您提供的可以重写如下并编译:

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();

It means that a Lambda expression of type TDelegate which contains a ([parameters]) => { some code }; cannot be converted to an Expression<TDelegate>. It's the rule.

Simplify your query. The one you provided can be rewritten as the following and will compile:

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();
放赐 2024-10-27 05:49:33

ArrObj 的基类型吗? Obj 类存在吗?仅当 Arr 是 Obj 的基本类型时,您的代码才有效。你可以尝试这个:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();

Is Arr a base type of Obj? Does the Obj class exist? Your code would work only if Arr is a base type of Obj. You can try this instead:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();
☆獨立☆ 2024-10-27 05:49:33

对于您的具体情况,主体用于创建变量,切换到 IEnumerable 将强制所有操作在客户端处理,我建议以下解决方案。

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

编辑:重命名为 C# 编码约定

For your specific case, the body is for creating a variable, and switching to IEnumerable will force all the operations to be processed on client-side, I propose the following solution.

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

Edit: Rename for C# Coding Convention

眼泪都笑了 2024-10-27 05:49:33

正如其他回复所述,您只能在 => 运算符右侧使用简单表达式。我建议这个解决方案,它只需要创建一个方法来执行您想要在 lambda 内部执行的操作:

public void SomeConfiguration() {
    // ...
    Obj[] myArray = objects.Select(o => Method()).ToArray();
    // ..
}

public Obj Method() {
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}

As stated on other replies, you can only use simple expressions to the right of the => operator. I suggest this solution, which consists of just creating a method that does what you want to have inside of the lambda:

public void SomeConfiguration() {
    // ...
    Obj[] myArray = objects.Select(o => Method()).ToArray();
    // ..
}

public Obj Method() {
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}
笔芯 2024-10-27 05:49:33

如果您来到这里是因为这是此错误的顶级谷歌结果,但您没有使用列表,那么您总是可以做一些快速而肮脏的事情,如下所示:

我的原始代码:

RuleFor(m => m.DocumentName).Must( ...etc...

我想深入了解m 并且我知道 m 的类型为 FileUploadDTO 并且在上面的表达式中它试图返回一个字符串,因此我添加了以下可以设置断点的方法:

private string GetIt(FileUploadDTO dto)
{
    return dto.FileName;
}

然后:

RuleFor(m => GetIt(m)).Must( ...etc...

If you came here because this is a top google result for this error but you aren't using a list, you can always do something quick and dirty like this:

my original code:

RuleFor(m => m.DocumentName).Must( ...etc...

I want to drill into m and I know m is of type FileUploadDTO and in the above expression it is trying to return a string so I add the following method that I can set a breakpoint on:

private string GetIt(FileUploadDTO dto)
{
    return dto.FileName;
}

Then:

RuleFor(m => GetIt(m)).Must( ...etc...
帅气尐潴 2024-10-27 05:49:33

我通过简单地定义一个函数来解决这个问题:

public Obj MyFunc(Obj o)
{
    var someLocalVar = o.someVar;

    return new Obj()
    { 
        Var1 = someLocalVar,
        Var2 = o.var2
    };
}
Obj[] myArray = objects.Select(o => MyFunc(o)).ToArray();

I got around this issue by simply defining a function:

public Obj MyFunc(Obj o)
{
    var someLocalVar = o.someVar;

    return new Obj()
    { 
        Var1 = someLocalVar,
        Var2 = o.var2
    };
}
Obj[] myArray = objects.Select(o => MyFunc(o)).ToArray();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文