有没有办法延迟 - 在执行后/执行期间对IQueryable <t>执行委托?</t>

时间:2010-02-02 19:14:45

标签: c# linq linq-to-sql delegates

我从业务层公开了一个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 个答案:

答案 0 :(得分:1)

轻松的方式

另一个更简单的选择是使用Iterator追加您需要的内容,请参阅下面的示例。这种方法的缺点是,在执行迭代时,所有内容都会被拉入内存,因此AppendData仅在返回的数据上执行。这类似于@Chris的选项,但每次要使用该方法时,您都不会被迫创建新的FuncSelect查询。

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包装器来添加自己的事件。

Here是一个关于撰写完整IQueryable提供程序的系列文章,该系列文章还会向您显示适合您的包装器的位置,最有可能在IQueryProvider附近。

祝你好运,希望这会有所帮助。

答案 1 :(得分:1)

您是否看过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;

答案 2 :(得分:0)

现在你正在使用一些ORM,对吗?我很确定你可以通过显式使用IE的IEnumerable版本而不是IQueryable来使用lambda表达式来实现这一点。

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

当查询实际执行时,它将获取Query()返回的所有数据,然后在内存中进行选择。

答案 3 :(得分:0)

我没有尝试,但我认为您可以使用automapper映射到返回IQuerible的不同或类似对象,并在映射上使用“AfterMap”以在查询完成后执行代码。