我试图在lambda表达式中调用一个控制器动作方法,如下所示。
此处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();
如果我像上面那样写,Create()
方法被完美调用,但是如果我删除了ToList()
,那么Create()
就不会被调用。
答案 0 :(得分:2)
问题是Select
方法实际上并没有那么多。当你迭代它的结果时,它会开始做一些事情。
也就是说,ToList
方法会迭代从Select
返回的迭代器,因此它会执行你的lambda表达式。
我想您想要获取结果并使用它做一些事情,如果是这样,将其分配给变量并迭代它:
foreach(var row in dtImporteddata.Rows.Cast<DataRow>().Select(...))
{
// do something with row
}
答案 1 :(得分:2)
LINQ方法可以分为两个阵营:那些总是返回结果的阵营(例如,FirstOrDefault
)和那些投射的不同形式的阵营他们。您可以将这些投影方法视为执行过滤操作。
请参阅what is a projection in LINQ, as in .Select()
无论如何,为了回答你的问题,LINQ并不总是执行你认为它正在执行的操作。在许多情况下,LINQ使用后续操作来添加过滤(或修改投影),并且只有在解析时,对结果的方法调用才会执行调用。
我怀疑这是这种情况。如果没有ToList
来电,您只需构建指令集,并且只有在您致电ToList
时,这些说明才会被解析为结果。
如果您实际上并未对List<DataRow>
提供的功能感到困扰,而您只想要一个可枚举的结果,请考虑使用ToArray
,因为它的开销低于ToList
。
答案 2 :(得分:2)
我建议在可重用组件中抽象创建功能,控制器和lambda都可以使用。例如,您可以创建一个具有以下签名的方法的类:
public void CreateDepartment(Department newDepartment)
Department
类可能会显示与FormCollection
相同的字段。
您可以直接在LINQ中使用新方法,如下所示:
dtImporteddata.Rows.Cast<DataRow>().ToList()
.ForEach(r => CreateDepartment(
new Department {
Name = r.Name,
....//rest of the properties
}));
通过这种方式,您还可以在“创建”操作中调用相同的方法。