使用lambda表达式调用控制器Action方法

时间:2022-12-01 23:20:50

I am trying to call a controller action method inside the lambda expression like below.

我试图在lambda表达式中调用控制器动作方法,如下所示。

Here dtImporteddata is my DataTable

这里dtImporteddata是我的DataTable

public class DepartmentController : Controller
{
      public ActionResult Create(FormCollection collection, int ParentDepartmentID)
    {
       return view();
    }
}


   dtImporteddata.Rows.Cast<DataRow>().Select(r => new DepartmentController().Create(new FormCollection{ 
                {"ParentDepartmentID","57"},
                {"DepartmentPrefix",r["Prefix"].ToString()},
                {"DepartmentID","0"},
                {"IsSpecialDepartment",null},
                {"Description",r["Description"].ToString()},
                {"Name",r["Name"].ToString()},
                {"LocationIDs.$.PackedValue","4;;;"}
             }, 0)).ToList();

if i write like above the Create() method is getting called perfectly but if i remove ToList() then the Create() is not getting called.

如果我像上面那样写,Create()方法被完美地调用,但如果我删除ToList(),则不会调用Create()。

3 个解决方案

#1


The problem is that the Select method actually doesn't do that much. It starts doing something when you iterate over its result.

问题是Select方法实际上并没有那么多。当你迭代它的结果时,它开始做一些事情。

That said, the ToList method does iterate over the iterator returned from Select, hence it executes your lambda expression.

也就是说,ToList方法会迭代从Select返回的迭代器,因此它会执行lambda表达式。

I guess you want to pick up the result and do something with it, if so, assign it to a variable and iterate over it:

我想你想拿起结果并用它做一些事情,如果是这样的话,把它分配给一个变量并迭代它:

foreach(var row in dtImporteddata.Rows.Cast<DataRow>().Select(...))
{
    // do something with row
}

#2


LINQ methods can be split into two camps: those which always return a result (eg, FirstOrDefault) and those which project a different form of what's being given to them. You can think of these projection methods as performing filtering operations.

LINQ方法可以分为两个阵营:总是返回结果的阵营(例如,FirstOrDefault)和那些投射给他们的不同形式的阵营。您可以将这些投影方法视为执行过滤操作。

See what is a projection in LINQ, as in .Select()

查看LINQ中的投影是什么,如.Select()

Anyway, to answer your question, LINQ doesn't always perform the operation that you might think it's performing. In many cases LINQ uses subsequent operations to add filtering (or modify the projection) and only when you resolve the method call to a result are the calls executed.

无论如何,为了回答你的问题,LINQ并不总是执行你认为它正在执行的操作。在许多情况下,LINQ使用后续操作来添加过滤(或修改投影),并且只有在解析方法调用结果时才执行调用。

I suspect that this is the case here. Without the ToList call you're only building the set of instructions, and only when you call ToList are these instructions resolved to a result.

我怀疑这是这种情况。如果没有ToList调用,您只需构建一组指令,并且只有在调用ToList时,这些指令才会被解析为结果。

If you're not actually bothered about the functionality offered by a List<DataRow> and you simply want an enumerable result, consider using ToArray as it has less overhead than ToList.

如果您实际上并不关心List 提供的功能,并且您只想要一个可枚举的结果,请考虑使用ToArray,因为它比ToList的开销更少。

#3


I would suggest abstracting the create functionality in a reusable component, that both the controller and your lambda can use. For example, you could create a class that has a method with the following signature:

我建议在可重用组件中抽象创建功能,控制器和lambda都可以使用。例如,您可以创建一个具有以下签名的方法的类:

public void CreateDepartment(Department newDepartment)

The Department class could probably expose the same fields as the FormCollection.

Department类可能会暴露与FormCollection相同的字段。

You could the use the new method directly in LINQ like so:

您可以直接在LINQ中使用新方法,如下所示:

dtImporteddata.Rows.Cast<DataRow>().ToList()
              .ForEach(r => CreateDepartment(
                                new Department {
                                                   Name = r.Name,
                                                   ....//rest of the properties
                                                }));

In this way, you would also be able to call the same method within the Create action.

这样,您还可以在Create操作中调用相同的方法。

#1


The problem is that the Select method actually doesn't do that much. It starts doing something when you iterate over its result.

问题是Select方法实际上并没有那么多。当你迭代它的结果时,它开始做一些事情。

That said, the ToList method does iterate over the iterator returned from Select, hence it executes your lambda expression.

也就是说,ToList方法会迭代从Select返回的迭代器,因此它会执行lambda表达式。

I guess you want to pick up the result and do something with it, if so, assign it to a variable and iterate over it:

我想你想拿起结果并用它做一些事情,如果是这样的话,把它分配给一个变量并迭代它:

foreach(var row in dtImporteddata.Rows.Cast<DataRow>().Select(...))
{
    // do something with row
}

#2


LINQ methods can be split into two camps: those which always return a result (eg, FirstOrDefault) and those which project a different form of what's being given to them. You can think of these projection methods as performing filtering operations.

LINQ方法可以分为两个阵营:总是返回结果的阵营(例如,FirstOrDefault)和那些投射给他们的不同形式的阵营。您可以将这些投影方法视为执行过滤操作。

See what is a projection in LINQ, as in .Select()

查看LINQ中的投影是什么,如.Select()

Anyway, to answer your question, LINQ doesn't always perform the operation that you might think it's performing. In many cases LINQ uses subsequent operations to add filtering (or modify the projection) and only when you resolve the method call to a result are the calls executed.

无论如何,为了回答你的问题,LINQ并不总是执行你认为它正在执行的操作。在许多情况下,LINQ使用后续操作来添加过滤(或修改投影),并且只有在解析方法调用结果时才执行调用。

I suspect that this is the case here. Without the ToList call you're only building the set of instructions, and only when you call ToList are these instructions resolved to a result.

我怀疑这是这种情况。如果没有ToList调用,您只需构建一组指令,并且只有在调用ToList时,这些指令才会被解析为结果。

If you're not actually bothered about the functionality offered by a List<DataRow> and you simply want an enumerable result, consider using ToArray as it has less overhead than ToList.

如果您实际上并不关心List 提供的功能,并且您只想要一个可枚举的结果,请考虑使用ToArray,因为它比ToList的开销更少。

#3


I would suggest abstracting the create functionality in a reusable component, that both the controller and your lambda can use. For example, you could create a class that has a method with the following signature:

我建议在可重用组件中抽象创建功能,控制器和lambda都可以使用。例如,您可以创建一个具有以下签名的方法的类:

public void CreateDepartment(Department newDepartment)

The Department class could probably expose the same fields as the FormCollection.

Department类可能会暴露与FormCollection相同的字段。

You could the use the new method directly in LINQ like so:

您可以直接在LINQ中使用新方法,如下所示:

dtImporteddata.Rows.Cast<DataRow>().ToList()
              .ForEach(r => CreateDepartment(
                                new Department {
                                                   Name = r.Name,
                                                   ....//rest of the properties
                                                }));

In this way, you would also be able to call the same method within the Create action.

这样,您还可以在Create操作中调用相同的方法。