Есть ли способ отложить выполнение делегата против IQueryable <T>после / во время выполнения? - PullRequest
4 голосов
/ 02 февраля 2010

Я предоставляю метод IQueryable из своего бизнес-уровня для использования на других уровнях. Я хотел бы выполнить функцию для каждого из элементов в перечислении, как только запрос будет выполнен на более низком уровне.

Похоже, должно быть событие, которое возникает после выполнения запроса, чтобы я мог затем обработать результаты этого общего уровня.

Что-то вроде:

public IQueryable<User> Query() 
{
    return _Repository.Query<User>().ForEachDelayed(u=> AppendData(u));
}

Я хочу, чтобы функция ForEachDelayed возвращала IQueryable без выполнения запроса. Идея состоит в том, что после выполнения запроса результаты передаются через этот делегат.

Есть ли что-то подобное там? Если нет, есть ли событие, подобное «IQueryable.OnExecute», на которое можно подписаться?

Любая помощь будет потрясающей - спасибо!

РЕДАКТИРОВАТЬ:

Я думал, что у меня есть ответ с этим:

var users = from u in _Repository.Query<User>()
            select AppendData(u);
return users;

Но теперь я получаю следующую ошибку:

Метод 'AppendData (User)' не поддерживает перевод на SQL.

Мне действительно нужен делегат для запуска ПОСЛЕ выполнения запроса.

Ответы [ 4 ]

1 голос
/ 04 февраля 2010

Вы смотрели на ToExpandable ()?

http://tomasp.net/blog/linq-expand.aspx

Вы всегда можете вызвать ToList () перед выполнением вашего кода - это вызовет SQL, затем вы можетеВаш код в наборе результатов -

var users = from u in _Repository.Query<User>().ToList();

//this will invoke AppendData() for each u
var retVal = from u in users
            select AppendData(u);

return retVal;
1 голос
/ 02 февраля 2010

Простой способ

Другой вариант, который намного проще, - добавить то, что вам нужно, с помощью Iterator, см. Пример ниже.Недостатком этого подхода является то, что все было бы извлечено в память во время выполнения итерации, так что AppendData выполняется только для возвращенных данных.Это похоже на параметр @Chris, но вы не обязаны создавать новый запрос Func и Select каждый раз, когда хотите использовать метод.

static void Main(string[] args)
{
    var data = new List<int> { 1, 2, 3, 4, 5 }.AsQueryable().AppendData();

    Console.WriteLine("Before execute");

    Console.Write("{ ");
    foreach (var x in data)
       Console.Write("{0}, ", x);

    Console.WriteLine( "}");

    Console.WriteLine("After execute");

    Console.Read();
}

// Append extra data. From this point on everything is in memory
// This should be generic, i.e. AppendData<T>, but I an easy way to "append"
static IEnumerable<int> AppendData(this IEnumerable<int> data)
{
    Console.WriteLine("Adding");
    foreach (var x in data)            
        yield return x * 2;
}

Трудный путь

Я не верю, что есть какие-то встроенные события, подобные этому, но вы, вероятно, могли бы добавить свое собственное, реализовав собственную оболочку IQueryable.

Здесь представляет собой серию написанияполный IQueryable провайдер, который также покажет вам, где вы можете разместить свою обертку, скорее всего около этого IQueryProvider.

Удачи и надеюсь, что это поможет.

0 голосов
/ 20 апреля 2013

Я не пробовал, но я думаю, что вы можете использовать automapper для сопоставления с другим или похожим объектом, возвращающим IQuerible, и использовать "AfterMap" в отображении для выполнения вашего кода после выполнения запроса.

0 голосов
/ 04 февраля 2010

Прямо сейчас вы используете ORM, правильно? Я почти уверен, что вы можете добиться этого, используя форму лямбда-выражения, явно используя версию select из IEnumerable вместо IQueryable.

var users = (_Repository.Query<User>() as IEnumerable<User>).Select(u => AppendDate(u)); 
return users; 

Когда запрос фактически выполняется, он извлекает все данные, возвращаемые Query (), а затем выполняет выборку в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...