有没有办法将 Linq 投影与扩展方法一起使用
我正在尝试使用 AutoMapper 和存储库模式以及流畅的界面,但在 Linq 投影方面遇到了困难。就其价值而言,当仅使用内存中的对象时,此代码可以正常工作。然而,当使用数据库提供程序时,它会在构造查询图时中断。我尝试了 SubSonic 和 Linq to SQL,但结果相同。感谢您的想法。
这是在所有场景中使用的扩展方法 - 这是问题的根源,因为不使用扩展方法一切都工作正常
public static IQueryable<MyUser> ByName(this IQueryable<MyUser> users, string firstName)
{
return from u in users
where u.FirstName == firstName
select u;
}
这是工作正常的内存中代码
var userlist = new List<User> {new User{FirstName = "Test", LastName = "User"}};
Mapper.CreateMap<User, MyUser>();
var result = (from u in userlist
select Mapper.Map<User, MyUser>(u))
.AsQueryable()
.ByName("Test");
foreach (var x in result)
{
Console.WriteLine(x.FirstName);
}
这里是使用 SubSonic(或 Linq to SQL 或其他)的同样的事情失败了。这就是我想通过扩展方法以某种方式完成的工作...
Mapper.CreateMap<User, MyUser>();
var result = from u in new DataClasses1DataContext().Users
select Mapper.Map<User, MyUser>(u);
var final = result.ByName("Test");
foreach(var x in final) // Fails here when the query graph built.
{
Console.WriteLine(x.FirstName);
}
这里的目标是避免必须手动将生成的“User”对象映射到“MyUser”域对象 - 换句话说,我我正在尝试找到一种使用 AutoMapper 的方法,因此我在需要数据库读取操作的任何地方都没有这种映射代码:
var result = from u in new DataClasses1DataContext().Users
select new MyUser // Can this be avoided with AutoMapper AND extension methods?
{
FirstName = v.FirstName,
LastName = v.LastName
};
I'm trying to use AutoMapper and a repository pattern along with a fluent interface, and running into difficulty with the Linq projection. For what it's worth, this code works fine when simply using in-memory objects. When using a database provider, however, it breaks when constructing the query graph. I've tried both SubSonic and Linq to SQL with the same result. Thanks for your ideas.
Here's an extension method used in all scenarios - It's the source of the problem since everything works fine without using extension methods
public static IQueryable<MyUser> ByName(this IQueryable<MyUser> users, string firstName)
{
return from u in users
where u.FirstName == firstName
select u;
}
Here's the in-memory code that works fine
var userlist = new List<User> {new User{FirstName = "Test", LastName = "User"}};
Mapper.CreateMap<User, MyUser>();
var result = (from u in userlist
select Mapper.Map<User, MyUser>(u))
.AsQueryable()
.ByName("Test");
foreach (var x in result)
{
Console.WriteLine(x.FirstName);
}
Here's the same thing using a SubSonic (or Linq to SQL or whatever) that fails. This is what I'd like to make work somehow with extension methods...
Mapper.CreateMap<User, MyUser>();
var result = from u in new DataClasses1DataContext().Users
select Mapper.Map<User, MyUser>(u);
var final = result.ByName("Test");
foreach(var x in final) // Fails here when the query graph built.
{
Console.WriteLine(x.FirstName);
}
The goal here is to avoid having to manually map the generated "User" object to the "MyUser" domain object- in other words, I'm trying to find a way to use AutoMapper so I don't have this kind of mapping code everywhere a database read operation is needed:
var result = from u in new DataClasses1DataContext().Users
select new MyUser // Can this be avoided with AutoMapper AND extension methods?
{
FirstName = v.FirstName,
LastName = v.LastName
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
嗯,我不知道 SubSonic 的 LINQ 实现。然而,问题的原因可能是 LINQ 提供程序无法使用“Mapper”调用。它期望一些可以翻译成 SQL 的东西。
顺便说一句,我会在“用户”查询上使用 .ByName() 而不是当前的实现。因为目前必须映射结果才能运行 .ByName()。因此,您从数据库中检索大量用户实例,映射它们并随后过滤它们。如果您在“用户”上使用 .ByName,它可以被转换为 SQL,而无需检索。
所以我猜这样的事情会起作用:
现在你将映射部分添加到末尾:
Mapper.CreateMap();
如果仍然不起作用,您可能需要强制 Mapper 部分使用 LINQ-to-Object:
Mapper.CreateMap();
顺便说一句,您可能想添加一个“SubSonic”标签,以便 SubSonic 专家回答您的问题。
Well I don't know SubSonic's LINQ-implementation. However the cause of the problem could be, that the LINQ-Provider fails to use the 'Mapper'-call. It expects something that is can be translated into SQL.
By the way, I would use the .ByName() on the 'User'-query instead of the current implementation. Because currently the result has to mapped in order to run the .ByName(). So you retrieve a lot of User-instance from the database, map them and filter them afterwards. If you would use .ByName on the 'User', it can be translated into SQL an never has to be retrieved.
So my guess it that something like this would work:
And now you add the mapping part to the end:
Mapper.CreateMap();
If it still doesn't work, you might need to force the usage of LINQ-to-Object for the Mapper-part:
Mapper.CreateMap();
By the way, you might wanna add a 'SubSonic'-tag, so that the SubSonic-experts answer your question.