LINQ to SQL 投影:Func 与 Inline
在使用 Func 的 LINQ to SQL 查询中使用投影时,我发现一些意外行为。示例代码比文字更能解释。
使用投影的基本 L2S lambda 查询:
db.Entities.Select(e => new DTO(e.Value));
它会转换为所需的 SQL:
SELECT [t1].[Value]
FROM [Entity] AS [t1]
但是,当将投影放入像这样的 Func 中时:
Func<Entity, DTO> ToDTO = (e) => new DTO(e.Value);
并且像这样调用:
db.Entities.Select(e => ToDTO(e));
SQL 现在会拉回表中的所有列,而不仅仅是投影中的一个:
SELECT [t1].[Id], [t1].[Value], [t1].[timestamp], [t1].[etc...]
FROM [Entity] AS [t1]
所以我的问题是,如何在 LINQ to SQL 实例化整个实体的情况下封装此投影?
需要记住的是,我使用的 DTO 有一个受保护的默认构造函数,因此我无法使用对象初始值设定项。由于 DTO 类无法修改,因此我必须创建一个子类来实现该行为。如果这是唯一的解决方案,那很好。
谢谢。
编辑:
感谢布莱恩提供的解决方案。我之前尝试过表达式,但无法弄清楚语法。这是工作代码:
Expression<Entity, DTO> ToDTO = (e) => new DTO(e.Value);
然后像这样调用它:
db.Entities.Select(ToDTO);
起初我试图这样调用它,但无法编译。这是调用 Func 的正确语法,但不是调用 Expression 的正确语法。
db.Entities.Select(e => ToDTO(e));
I am finding some unexpected behavior when using a projection in a LINQ to SQL query using a Func. Example code will explain better than words.
A basic L2S lambda query using projection:
db.Entities.Select(e => new DTO(e.Value));
It translates to the desired SQL:
SELECT [t1].[Value]
FROM [Entity] AS [t1]
However, when the projection is put into a Func like this:
Func<Entity, DTO> ToDTO = (e) => new DTO(e.Value);
And called like this:
db.Entities.Select(e => ToDTO(e));
The SQL is now pulling back all of the columns in the table, not just the one in the projection:
SELECT [t1].[Id], [t1].[Value], [t1].[timestamp], [t1].[etc...]
FROM [Entity] AS [t1]
So my question is, how do I encapsulate this projection without the LINQ to SQL instantiating the whole Entity?
Things to keep in mind, the DTO I am using has a protected default constructor, so I can't use an object initializer. And since the DTO class cannot be modified, I'd have to make a subclass to implement that behavior. Which is fine, if that's the only solution.
Thanks.
Edit:
Thanks to Brian for the solution. I had previously tried an Expression but couldn't figure out the syntax. Here's the working code:
Expression<Entity, DTO> ToDTO = (e) => new DTO(e.Value);
Then call it like this:
db.Entities.Select(ToDTO);
At first I was trying to call it like this, which wouldn't compile. This is the proper syntax for calling a Func, but not an Expression.
db.Entities.Select(e => ToDTO(e));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能需要创建一个
Expression
,而不是Func
IQueryable 扩展方法适用于
Expression
,而不是Func
通过传入
Func
,您可能会调用IEnumerable
扩展方法,这就是 Linq2Sql 如此运行的原因。You probably need to create an
Expression
, not aFunc
IQueryable extension methods work with
Expression
s, notFunc
sBy passing in a
Func
, you are probably invoking theIEnumerable
extension method, which is why Linq2Sql is acting the way it is.