2010-01-21 85 views
0

我想使用AutoMapper和一个存储库模式以及流畅的界面,并且在Linq投影中运行困难。对于它的价值,只需使用内存中的对象,此代码就可以正常工作。但是,在使用数据库提供程序时,它在构建查询图时会中断。我已经尝试了SubSonic和Linq到SQL,结果相同。感谢您的想法。有没有办法使用Linq投影和扩展方法

这里是所有方案中的使用的扩展方法 - 这是问题的根源,因为一切工作正常,而无需使用扩展方法

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

好吧,我不知道亚音速的LINQ的实现。但是,问题的原因可能是,LINQ提供程序无法使用“Mapper”调用。它期望可以转换成SQL的东西。

顺便说一句,我会在'用户'查询中使用.ByName()而不是当前的实现。因为当前结果必须映射才能运行.ByName()。所以你从数据库中检索了很多User-instance,然后映射它们并过滤它们。如果你在'用户'上使用.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); 
} 

如果仍然无法正常工作,您可能需要强制的LINQ到对象的映射器部分使用: 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专家可以回答您的问题。

+0

我想到了先调用ToList的方法,但是我想避免直到代码实际需要枚举数据时才调用它。换句话说,你的中间代码片段在foreach循环中的枚举器调用中碰到数据库(在这种情况下是一件好事)。当ToList被调用时,您的最后一个片段会触发数据库。这对我来说不起作用,因为扩展方法不在数据库项目中...... IoC的情况,它是注入的一对数据库实现之一。 – 2010-01-21 22:10:34