EF + SingleTon

54 views
Skip to first unread message

Carlos Abdalla

unread,
Sep 20, 2011, 5:35:01 PM9/20/11
to dotnetar...@googlegroups.com
Galera, é recomendável, altamente recomendável ou não é recomendável ?

Pergunto isso pois em um projeto que peguei estava dando vários problemas com o EF e sua persistência, mas eu vi que estava usando uma arquitetura mto complexa, com mapper, facade e afins dando umas 7 ou 8 camadas, ai eu fiz um contexto singleton e parou os bugs, mas eu realmente nao estou feliz com essa solução.

Oque me dizem ?

Obrigado!

João Bateloche

unread,
Sep 20, 2011, 6:06:08 PM9/20/11
to dotnetar...@googlegroups.com

Antes de discutirmos se é recomendável, esta abordagem atende suas necessidades? E por que você não gostou da solução?

Já li alguma coisa sobre perda do contexto, mas nunca tive problemas.

abs.
João Bateloche

> --
> Você recebeu esta mensagem porque faz parte do grupo .Net Architects hospedado no Google Groups.
> Para postar envie uma mensagem para dotnetar...@googlegroups.com
> Para sair do grupo envie uma mensagem para dotnetarchitec...@googlegroups.com
> Para mais opções visite o grupo em http://groups.google.com/group/dotnetarchitects?hl=pt-br

Carlos Abdalla

unread,
Sep 20, 2011, 6:10:00 PM9/20/11
to dotnetar...@googlegroups.com
Então, na verdade ele atendeu, mas alguma coisa me diz que não foi uma boa solução, fora que estou com medo dele ir crescendo e estourar memoria.... 

Sei la, por enquanto esta atendendo, mas alguma coisa me diz que vai dar m.... !hh hahahahahha

Eu não gosto de dar soluções sem estar embasado que aquilo foi uma boa saida, mas eu precisava resolver muito rapido então veio essa solucionática.. na verdade ja faz um tempo que fiz isso, e até agora nao deu problema... mas esta martelando na minha cabeça...



2011/9/20 João Bateloche <jbate...@gmail.com>

Bruno D'Alessio

unread,
Sep 20, 2011, 7:41:37 PM9/20/11
to dotnetar...@googlegroups.com
Engraçado, muito engraçado...

Estou tendo problema em uma APP legada que utiliza Singleton no EF.

Funciona bem por um certo tempo, depois a aplicação voa e apresenta: "Execution of the command requires an open and available connection. The connection's current state is broken."

Como trabalhei pouco com EF, estou lendo tudo (encontro cada besteira por ai, enfim...), mas tudo aponta para o Singleton.

Estou estudando o caso ainda, até esgotar, pq gosto de dar um "tiro" só!

Vi algo tambem sobre o lifecycle do contexto controlado por requisições ao repository, implementando IDisposable no mesmo e chamando o Dispose ao final da requisição, derrubando o contexto atual e renovando a instancia.

Achei tiro de canhão no mosquito.

Mas como disse ainda estou estudando...

Aproveitando, quem tiver passado por isso e tiver uma "luz", agradeço!
O Extract Method é seu amigo!

"Vocês riem de mim por ser diferente, eu rio de vocês por serem todos iguais..." (Bob Marley)

Bruno D'Alessio
Arquiteto de Software
(21) 9441-1214
GTALK: bruno...@gmail.com
MSN: brun...@hotmail.com


Carlos Abdalla

unread,
Sep 20, 2011, 7:44:36 PM9/20/11
to dotnetar...@googlegroups.com
Tbm estou estudando bem o EF e estou gostando mto do que estou lendo... e a cada vez q leio eu vejo q Singleton eh ruim...

Olha o link:

Att.
Carlos Abdalla


David Anderson Lino de Sousa

unread,
Sep 20, 2011, 7:48:42 PM9/20/11
to dotnetar...@googlegroups.com
@Bruno, A alternativa do IDisposable é ruim quando você usa LazyLoading, pois quando você vai acessar as propriedades, e o contexto foi destruído dá exceção.

@Carlos Eu tive problemas com lifecycle do EF, no meu caso era uma aplicação web, então usei um container de DI, e ele controlava o ciclo de vida do contexto, Sendo assim, eu tinha um, e apenas um, contexto por request. Tá aguentando o tranco, em pico o sistema tem cerca de 1k acessos simultâneos e tá lá firme e forte. Se seu caso é um app Desktop, talvez seja interessante ter 1 contexto por app... Não sei te ajudar muito neste caso.

Atenciosamente,
David Anderson Lino de Sousa

---

Systems Engineer @ C.E.S.A.R.
BSc. in Computer Science 





2011/9/20 Carlos Abdalla <caab...@gmail.com>

Bruno D'Alessio

unread,
Sep 20, 2011, 7:54:34 PM9/20/11
to dotnetar...@googlegroups.com
@David gostei da ideia de controlar o lifecycle por DI.

Explique com mais detlahes se puder por favor.


Abraço!

Bruno D'Alessio

unread,
Sep 20, 2011, 7:55:45 PM9/20/11
to dotnetar...@googlegroups.com
Em tempo:  @Carlos, obrigado pelo link, bem util!

Carlos Abdalla

unread,
Sep 20, 2011, 7:57:01 PM9/20/11
to dotnetar...@googlegroups.com
@David a app estava usando assim, mas devido a muitas coisas errada na app ( o pessoal salvava uma facade no viewstate ) a facade acessava uma mapper a mapper o contexto e ai ele se perdia todo, ai eu mudei para singleton, e problema solucionado... nem sei se o problema era esse mesmo mas como nao tinha prazo para procurar o problema e arrumar de maneira correta, e essa solucionatica resolveu... mas eu nao estou contente com a solucao... 

Eu uso o EF dessa maneira descrita por você em ecommerces e nunca tive problema... hahahaha eh essa app maluca ai.. com umas 8 camadas... 

Essa app eh web... 

Att.

Carlos Abdalla


David Anderson Lino de Sousa

unread,
Sep 20, 2011, 8:08:44 PM9/20/11
to dotnetar...@googlegroups.com
@Bruno Eu usei o Ninject neste projeto, eu tb tinha repositórios, e os repositórios concretos recebiam por DI um DbContext, o NInject é quem instanciava os repositórios, e por consequência os contextos, ele possui uma função InRequestScope, que garante que é usada sempre a mesma instância num determinado request (tb tem outras opções de lifecycle, inclusive singleton)

@Carlos Tenso... Tenta refatorar pra evitar o singleton... Acho que vai dar problemas de concorrência.. não? 

Carlos Abdalla

unread,
Sep 20, 2011, 8:20:27 PM9/20/11
to dotnetar...@googlegroups.com
Por enquanto não reclamaram, acho q não teria problema de concorrência não!!! ahhhahahaha

Eu refatoro com maior prazer, ja ia começar a retirar as 8 camadas e as facades salvas na VS. hahahahaha


Bom.. mas como não sei se vão me dar o prazo... vai ficar assim até o proximo problema... mas uma coisa eu sei, não pretendo usar Singleton em meus projetos com EF.. a não ser que me convençam do contrario.

David, mto obrigado pelas dicas.!


Carlos Abdalla


David Anderson Lino de Sousa

unread,
Sep 20, 2011, 8:23:08 PM9/20/11
to dotnetar...@googlegroups.com
Sem problemas, precisando estamos aí!

Bruno D'Alessio

unread,
Sep 20, 2011, 8:32:39 PM9/20/11
to dotnetar...@googlegroups.com
A galera que desenvolveu utilizou Singleton, estou avaliando uma refatoração, se não der certo vou verificar a possibilidade do DI controlar o LC do contexto.

Obrigado pessoal!

Juan Lopes

unread,
Sep 20, 2011, 8:37:57 PM9/20/11
to dotnetar...@googlegroups.com
DbContext não é thread-safe. Você vai ter problemas.

2011/9/20 Bruno D'Alessio <bruno...@gmail.com>

Waner

unread,
Sep 20, 2011, 8:36:49 PM9/20/11
to dotnetar...@googlegroups.com
Carlos, 

    Tive o mesmo problema com uma aplicação, a medida que o número de usuários subia (~2k), ela perdia a conexão. Resolvi com singleton também. 
    O negócio é que se você coloca o atributo da instancia como static ele fica único pro application pool (web) inteiro. Logo, independente das sessões dos usuários, o objeto vai ser único pra todos eles. Nesse caso você tem que tomar cuidado e colocar readonly nesse atributo (threadSafe) ou lock no instanciamento, além é claro, verificar se a a conexão está ativa no contexto pra levantar ela quando necessário. 

[]'s
---------------
Waner O. Miranda .'.




2011/9/20 Carlos Abdalla <caab...@gmail.com>

Juan Lopes

unread,
Sep 20, 2011, 8:40:23 PM9/20/11
to dotnetar...@googlegroups.com
O modificador readonly num campo não torna o objeto que ele referencia thread-safe.

2011/9/20 Waner <wanerm...@gmail.com>

Bruno D'Alessio

unread,
Sep 20, 2011, 9:49:10 PM9/20/11
to dotnetar...@googlegroups.com
Opa agora sim, alguem falou exatamente no ponto que estou analisando.

Tanto que alterei meu singleton para threadSafe utlizando um object com lock().

Tipo isso:
     static ContextDB instance = null;
     static readonly object lockObject = new object();

        public static
ContextDB Instance
        {
            get
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new ContextDB();
                    }
                    return instance;
                }
            }
        }


Amenizou o erro (sim amenizou, acredita?), mas não adiantou, mas ja consigo ver a luz da solução!

Carlos Abdalla

unread,
Sep 20, 2011, 10:01:28 PM9/20/11
to dotnetar...@googlegroups.com
A app estava usando assim o contexto, e dava uns erros malucos, ai mudei pro singleton e parou...

Mas eu ainda sim prefiro dessa maneira, ou usando DI.

Mas sinceramente, por tudo que tenho lido, não deveriamos ter problemas usando normalmente o contexto, deveria funcionar até com o que o proprio EF gera ou usando Templates (T4) para nos gerar esse contexto, me corrijam se eu estiver falando besteira.


Att.
Carlos Abdalla


Waner

unread,
Sep 20, 2011, 11:45:40 PM9/20/11
to dotnetar...@googlegroups.com
Bruno, 

     Além da instância do contexto, tenta controlar também o estado da conexão. Muitas vezes o banco pode derrubá-la por inatividade ou tempo de idle. Logo se tiver close, você pode escolher reconstrói a instancia ou tenta levantar a conexão. 

[]'s
---------------
Waner O. Miranda .'.




2011/9/20 Bruno D'Alessio <bruno...@gmail.com>

Acaz Souza Pereira

unread,
Sep 21, 2011, 7:49:42 AM9/21/11
to dotnetar...@googlegroups.com
@Bruno,

Estou desenvolvendo uma app que faz usa do Contexto do EF em Singleton, ainda não tive nenhum problema:

public class DbContextFactory
{
    private static volatile DbContextFactory _dbContextFactory;
    private static readonly object SyncRoot = new Object();
    public DbContext Context;

    public static DbContextFactory Instance
    {
        get
        {
            if (_dbContextFactory == null)
            {
                lock (SyncRoot)
                {
                    if (_dbContextFactory == null)
                        _dbContextFactory = new DbContextFactory();
                }
            }
            return _dbContextFactory;
        }
    }

    public DbContext GetOrCreateContext()
    {
        if (this.Context == null)
            this.Context = new DbContext(ConfigurationManager.AppSettings["DefaultConnectionString"]);

        return Context;
    }
}


Utilizando Ninject configurado dessa maneira:

Bind<IDbContext>().ToConstant(DbContextFactory.Instance.GetOrCreateContext());
[Acaz Souza Pereira]

MSN/GTalk: acaz...@gmail.com
Skype: acazsouza
Cel:  (31) 8706-4103

twitter.com/acazsouza

acazsouza.com.br

Juan Lopes

unread,
Sep 21, 2011, 8:12:47 AM9/21/11
to dotnetar...@googlegroups.com
Mais uma vez. DbContext NÃO é thread-safe. Vocês só não estão vendo problema porque não fizeram o teste certo.

2011/9/21 Acaz Souza Pereira <acaz...@gmail.com>

Acaz Souza Pereira

unread,
Sep 21, 2011, 8:15:36 AM9/21/11
to dotnetar...@googlegroups.com
Mas @Juan, pelo que li, usar uma instância do Contexto por request é uma boa prática.

Juan Lopes

unread,
Sep 21, 2011, 8:42:19 AM9/21/11
to dotnetar...@googlegroups.com

Por request sim, não uma unica no sistema inteiro.

Sent from mobile device.

>>> *[Acaz Souza Pereira]*
>>>
>>> *MSN/GTalk:* acaz...@gmail.com
>>> *Skype:* acazsouza
>>> *Cel:* (31) 8706-4103

>>>
>>> twitter.com/acazsouza
>>>
>>> acazsouza.com.br
>>>
>>>
>>> --
>>> Você recebeu esta mensagem porque faz parte do grupo .Net Architects
>>> hospedado no Google Groups.
>>> Para postar envie uma mensagem para dotnetar...@googlegroups.com
>>> Para sair do grupo envie uma mensagem para
>>> dotnetarchitec...@googlegroups.com
>>> Para mais opções visite o grupo em
>>> http://groups.google.com/group/dotnetarchitects?hl=pt-br
>>>
>>
>> --
>> Você recebeu esta mensagem porque faz parte do grupo .Net Architects
>> hospedado no Google Groups.
>> Para postar envie uma mensagem para dotnetar...@googlegroups.com
>> Para sair do grupo envie uma mensagem para
>> dotnetarchitec...@googlegroups.com
>> Para mais opções visite o grupo em
>> http://groups.google.com/group/dotnetarchitects?hl=pt-br
>>
>
>
>
> --
> *[Acaz Souza Pereira]*
>
> *MSN/GTalk:* acaz...@gmail.com
> *Skype:* acazsouza
> *Cel:* (31) 8706-4103

Bruno D'Alessio

unread,
Sep 21, 2011, 10:16:24 AM9/21/11
to dotnetar...@googlegroups.com
É exatamente o que estou refatorando!

Para ter o lifecycle gerido pelo Ninject e passar a ser por request e não "fulltime".

Juan Lopes

unread,
Sep 21, 2011, 10:22:27 AM9/21/11
to dotnetar...@googlegroups.com
Aliás, mesmo por request pode ser um problema se você abre outras threads durante o request.

2011/9/21 Bruno D'Alessio <bruno...@gmail.com>

Vinicius Quaiato

unread,
Sep 21, 2011, 10:27:48 AM9/21/11
to dotnetar...@googlegroups.com
foreach(var coisa in coisas){
   //abre threads e insere vários caras no contexto

Bruno D'Alessio

unread,
Sep 21, 2011, 10:28:39 AM9/21/11
to dotnetar...@googlegroups.com
Ja fiz um teste e garanti o fincionamento em apenas um repository, por request, o erro do mal não aparece!

Que na verdade são 2 erros.

O primeiro avisa que o estado da connction é broken.
E o erro a seguir é contexto "preso" a outra thread.

Com requisições por request esses erros acabaram.

Detalhe, o erro só aparece depois de um tempo de uso e acima de 1k de usuarios.

Estou utilizando WCAT para simular os acessos!

Ygor Thomaz

unread,
Sep 21, 2011, 11:17:24 AM9/21/11
to dotnetar...@googlegroups.com
Singleton na maioria das vezes é uma armadilha. Ver o ponto de vista do Quaiato, achei interessante quando li na epoca: http://viniciusquaiato.com/blog/singletons-sao-um-problema-veja/

Eu normalmente sempre fecho qualquer contexto apos uma requisição. Isso não torna mais lento, pelo menos no Oracle com ODP.NET ele fez uma boa quantidade de ponto de acerto no cache do Oracle.

Best regards,

--
Ygor Thomaz
Certified ScrumMaster (CSM)
Certified Scrum Product Owner (CSPO)
Website: http://www.ygorthomaz.com/ | Twitter: @ygorthomaz
"With Great Power Comes Great Responsibility." Uncle Ben, Spiderman

Walter

unread,
Sep 22, 2011, 9:11:51 AM9/22/11
to .Net Architects
Bom dia, Carlos,

Tive esse problema também na última semana.

Minha equipe desenvolveu os métodos do repositório sempre instanciando
um novo contexto. Comecei a detectar diversos problemas, como por
exemplo, depois de alterar uma entidade precisava buscá-la novamente
antes de atualizar, visto que estava criando um novo contexto.

Parti para idéia de singleton e tudo ficou mais rápido e otimizado.

Achei até uma implementação interessante em um artigo sobre a criação
de uma factory de contextos que é muito interessante para aplicações
maiores onde existe a necessidade de você implementar diversos
contextos: http://www.pantanet.net/profiles/blogs/adonet-entity-framework-41
- pelo que entendi, o contexto é como um dataset em memória de tudo
que ele precisa naquele escopo... ficar criando um novo a cada
solicitação só vai subutilizar o recurso. Você só tem que ter certo
cuidado quando existir concorrência dentro da mesma aplicação...
ocorrem vários problemas...

Não sei se ajudei, mas sua abordagem não está errada.

Rodrigo Silva de Andrade

unread,
Sep 22, 2011, 3:38:34 PM9/22/11
to dotnetar...@googlegroups.com
context nao eh thread safe, usar como singleton vai te trazer problemas com certeza. Você tem que definir um escopo para o context. 

Pra web costumam usar 1 context por request.

2011/9/22 Walter <walterlui...@gmail.com>

Rene Felix Correa

unread,
May 15, 2012, 10:21:54 PM5/15/12
to dotnetar...@googlegroups.com
Alguem teria a implementação que foi feita criando um context por request ?


2011/9/22 Rodrigo Silva de Andrade <dang...@gmail.com>



--
Rene Felix Correa
Analista Desenvolvedor
http://renefc3.wordpress.com

paulo ortins

unread,
May 16, 2012, 7:03:34 AM5/16/12
to dotnetar...@googlegroups.com
Rene, eu tenho uma implementação usando Ninject pra criar os context de acordo com o HttpContext, serve ?
Atenciosamente,
Paulo Ortins.
(71) 8834 - 0628
Check out my blog !

Igor

unread,
May 16, 2012, 7:58:10 AM5/16/12
to dotnetar...@googlegroups.com
Não é recomendado por conta do UnitOfWork do EF. Que no caso é o DbContext.

Dyego Costa

unread,
May 16, 2012, 7:40:43 AM5/16/12
to dotnetar...@googlegroups.com
Eu uso algo assim já faz um bom tempo, não tive problemas
public class AccountRepository : BaseRepository<Account>, IAccountRepository
    {
        public AccountRepository(IDatabaseFactory databaseFactory)
            : base(databaseFactory)
        {
        }
    }


public class DatabaseFactory : Disposable, IDatabaseFactory
    {
        private [NomeDoProjeto]Context _dataContext;

        public [NomeDoProjeto]Context Get()
        {
            return _dataContext ?? (_dataContext = new SkillMeterContext());
        }

        protected override void DisposeCore()
        {
            if (_dataContext != null)
                _dataContext.Dispose();
        }
    }
public static IUnityContainer GetUnityContainer()
        {
            IUnityContainer container = new UnityContainer();

            container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HttpContextLifetimeManager<IDatabaseFactory>());
            container.RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>());            
            container.RegisterType<IAccountRepository, AccountRepository>(new HttpContextLifetimeManager<IAccountRepository>());
}

Tudo em suas devidas camadas, claro.

Abraços.

Dyego Costa



Date: Wed, 16 May 2012 08:03:34 -0300
Subject: Re: [dotnetarchitects] Re: EF + SingleTon
From: paulo....@gmail.com
To: dotnetar...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages