我正在尝试使用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);
}
这里的目标是避免必须手动将生成的“用户”对象映射到“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
};
答案 0 :(得分:0)
我不知道SubSonic的LINQ实现。然而,问题的原因可能是LINQ-Provider无法使用'Mapper'调用。它期望可以将某些东西翻译成SQL。
顺便说一下,我会在'User'查询中使用.ByName()而不是当前的实现。因为当前结果必须映射才能运行.ByName()。因此,您从数据库中检索了大量的User-instance,映射它们并在之后过滤它们。如果你在'User'上使用.ByName,它可以被翻译成SQL,永远不必检索。
所以我猜这样的东西会起作用:
public static IQueryable<User> ByName(this IQueryable<User> users,
string firstName)
{
return from u in users
where u.FirstName == firstName
select u;
}
现在您将映射部分添加到结尾: Mapper.CreateMap();
var result = from u in new DataClasses1DataContext().Users.ByName("Test")
select Mapper.Map<User, MyUser>(u);
// now the 'ByName'-constain can be ran on the database
foreach(var x in result)
{
Console.WriteLine(x.FirstName);
}
如果它仍然不起作用,您可能需要强制使用Mapper-part的LINQ-to-Object: Mapper.CreateMap();
var result = DataClasses1DataContext().Users.ByName("Test").ToList();
// now the result is a regualar list, so LINQ-to-object is used for the mapping part
var final = from u in result
select Mapper.Map<User, MyUser>(u);
foreach(var x in final)
{
Console.WriteLine(x.FirstName);
}
顺便说一句,您可能想添加一个'SubSonic'标签,以便SubSonic专家回答您的问题。