Pergunta

Imagine que eu tenha o seguinte:

private IEnumerable MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      return dc.tablename.Select(row => row.parameter == a);
   }
}

private void UsingFunc()
{
   var result = MyFunc(new a());

   foreach(var row in result)
   {
      //Do something
   }
}

De acordo com a documentação da execução LINQ vai adiar até que eu enumerar real o resultado, que ocorre na fila do foreach. No entanto, a instrução using deve forçar o objeto a ser recolhidos de forma fiável no final da chamada para MyFunct ().

O que realmente acontece, quando é que o triturador de execução e / ou o resultado prazo?

A única coisa que posso pensar é a execução diferido é calculado em tempo de compilação, então a chamada real é movido pelo compilador para a primeira linha do foreach, fazendo com que o usando para executar corretamente, mas não executar até que a linha foreach ? Existe um guru lá fora que pode ajudar?

EDIT: NOTA: Este código não trabalho, eu só não entendo como

.

Eu fiz alguma leitura e percebi no meu código que eu tinha chamado o método de extensão ToList () que, naturalmente, enumera o resultado. O comportamento da resposta assinalada é perfeitamente correta para a questão real respondeu.

Pedimos desculpas por qualquer confusão.

Foi útil?

Solução

Eu esperaria que simplesmente não trabalho; o Select é diferido, de modo nenhum dado foi consumido neste momento. No entanto, desde que você tenha eliminado o contexto de dados (antes de sair MyFunc), nunca será capaz de obter dados. A melhor opção é passar os dados ao contexto em o método, para que o consumidor pode escolher a vida. Além disso, eu recomendaria o retorno IQueryable<T> para que o consumidor pode "compor" o resultado (ou seja, adicionar OrderBy / Skip / Take / Where etc, e tê-lo impactar a consulta final):

// this could also be an instance method on the data-context
internal static IQueryable<SomeType> MyFunc(
    this MyDataContext dc, parameter a)
{
   return dc.tablename.Where(row => row.parameter == a);
}

private void UsingFunc()
{
    using(MyDataContext dc = new MyDataContext()) {
       var result = dc.MyFunc(new a());

       foreach(var row in result)
       {
           //Do something
       }
    }
}

Atualização: se você (comentários) não querem execução adiar (ou seja, você não quer que o tráfico de chamador com o contexto de dados), então você precisa para avaliar os resultados. Você pode fazer isso chamando .ToList() ou .ToArray() sobre o resultado para o buffer os valores.

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      // or ToList() etc
      return dc.tablename.Where(row => row.parameter == a).ToArray();
   }
}

Se você quiser mantê-lo adiado neste caso, então você precisa usar um "bloco de iterator":

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      foreach(SomeType row in dc
          .tablename.Where(row => row.parameter == a))
      {
        yield return row;
      }
   }
}

Esta é agora adiada sem passar o contexto de dados ao redor.

Outras dicas

Acabei de publicar uma outra solução execução adiada para este problema aqui , incluindo este código de exemplo:

IQueryable<MyType> MyFunc(string myValue)
{
    return from dc in new MyDataContext().Use()
           from row in dc.MyTable
           where row.MyField == myValue
           select row;
}

void UsingFunc()
{
    var result = MyFunc("MyValue").OrderBy(row => row.SortOrder);
    foreach(var row in result)
    {
        //Do something
    }
}

O método de extensão Use() age essencialmente como um bloco using adiada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top