Reputation: 1621
I am trying to call a controller action method inside the lambda expression like below.
Here dtImporteddata
is my 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.
Upvotes: 2
Views: 838
Reputation: 4450
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:
public void CreateDepartment(Department newDepartment)
The Department
class could probably expose the same fields as the FormCollection
.
You could the use the new method directly in LINQ like so:
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.
Upvotes: 2
Reputation: 7959
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.
See what is a projection in LINQ, as in .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.
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.
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
.
Upvotes: 2
Reputation: 157118
The problem is that the Select
method actually doesn't do that much. It starts doing something when you iterate over its result.
That said, the ToList
method does iterate over the iterator returned from Select
, hence it executes your lambda expression.
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
}
Upvotes: 2