Есть ли способ использовать проекции Linq с методами расширения - PullRequest
0 голосов
/ 21 января 2010

Я пытаюсь использовать 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
                          };

1 Ответ

0 голосов
/ 21 января 2010

Ну, я не знаю LINQ-реализацию SubSonic. Однако причина проблемы может заключаться в том, что LINQ-провайдер не может использовать вызов Mapper. Он ожидает что-то, что может быть переведено в SQL.

Кстати, я бы использовал .ByName () в пользовательском запросе вместо текущей реализации. Потому что в настоящее время результат должен отображаться для запуска .ByName (). Таким образом, вы извлекаете много пользовательских экземпляров из базы данных, отображаете их и затем фильтруете. Если вы используете .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-to-Object для Mapper-части: 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 ответили на ваш вопрос.

...