Para quem utiliza Entity Framework, o acesso aos dados é fornecido pelo contexto (gerado pelo Entity Data Model Designer). Ora, o contexto gerado pela ferramenta deriva de System.Data.Objects.ObjectContext que por sua vez implementa IDisposable. Dizem as boas práticas que um objecto que seja IDisposable deve ser usado da seguinte forma: public IEnumerable<Product> Products { get; set; }
void Sample1()
{
using (var ctx = new NorthwindEntities())
{
Products = ctx.Products.Where(p => p.UnitPrice < 10);
}
}
Simples e eficaz. Mas, agora imaginemos que quero carregar a lista de produtos num outro objecto e até a posso colocar no construtor ou na inicialização directa:
class SomeObject { public IEnumerable<Product> Products { get; set; } }
void Sample2()
{
using (var ctx = new NorthwindEntities())
{
SomeObject someObject1 = new SomeObject()
{
Products = ctx.Products.Where(p => p.UnitPrice < 10)
};
}
//someObject1 not available here...
}
Então temos um problema: é que a utilização do objecto criado fica restrita ao corpo da estrutura using. É certo que se pode declarar o objecto fora da estrutura ou simplesmente expandir a estrutura, mas isso nem sempre é desejável. Para contornar esta situação costumo utilizar um pequeno método inspirado na inversão de controlo, assim:
public partial class NorthwindEntities
{
public static T Execute<T>(Func<NorthwindEntities, T> f)
{
using (var ctx = new NorthwindEntities())
{
return f(ctx);
}
}
}
Neste caso, coloquei o método na própria classe de contexto, mas pode ser colocado numa qualquer classe estática. A razão de o ter colocado directamente no contexto é que é dependente do próprio contexto devido à inicialização local do mesmo. Com esta pequena ajuda, a mesma consulta pode ser escrita assim:
void Sample3()
{
Products = NorthwindEntities.Execute(ctx => ctx.Products.Where(p => p.UnitPrice < 10));
}
Ou assim:
void Sample4()
{
SomeObject someObject1 = new SomeObject()
{
Products = NorthwindEntities.Execute(ctx => ctx.Products.Where(p => p.UnitPrice < 10))
};
//someObject1 available here...
}
Claro que este exemplo apenas tem utilização quando o contexto apenas é necessário para uma única consulta. Para mais do que uma consulta deverá sempre ser utilizado o padrão standard.