none
Modelo de entidades com 700 Tabelas - (NHibernate ou Entity Framework)?

    Question

  • Bom Dia,

    Trabalho com Entity Framework e ele tem funcionado perfeitamente. Hoje temos 250 tabelas em nosso domínio. O banco vai crescer e chegar a 700 tabelas em 6 meses pelos projetos que temos para expandir o software (ERP). Noto que hoje o sistema pode ganhar mais performance se eu aplicar algumas sugestões no modelo como separa em medelos menores por módulos, o faria eu ter 7 EMDX. Entretanto, O Entity Framework em nosso caso (Uma aplicação ASP.NET) necessita da pré-criação de views para ganho de performance e em seu primeiro acesso, devido a ele ter que carregar o modelo, ele se torna lento e tivemos que aplicar uma lógica para liberação da interface de login somente quando o contexto é carregado. Após isso a peformance é bem agradável.

    Minha pesquisa está sendo realizada em cima dessa expansão do modelo. Gostaria de receber sugestões sobre se continuo com EF ou tento utlizar o NHibernate devido a vantagens e desvantagens de grandes modelos. Seria interessante utlizar WCF para comunicação das entidades com a interface para ganho de performance?


    C#, asp.Net desenvolvedor
    Thursday, October 20, 2011 12:04 PM

All replies

  • Olá Giovane,

    É muito bom saber que um sistema tão grande utiliza o EF, e saber que está em mãos de profissionais preocupados com performance e bom uso de sua camada de acesso a dados!

    Seguem comentários:
    1 - Não acredito que seja necessário mudar para o NHibernate, o EF da conta do recado muito facilmente.
    2 - Vc comenta que existe uma certa demora na criação do contexto. Como esses contextos foram criados? Manualmente ou via interface do Visual Studio? Acredito que devido a quantidade de tabelas, no construtor da classe do seu contexto deva existir uma quantidade grande de inicializações das propriedades que fazem o mapeamento para as tabelas, desta forma:

    private Table<DataItem> _dataItems;
    
    public DataBaseContext(string connectionString)
        : base(connectionString)
    {
        this._dataItems = this.GetTable<DataItem>();
    }
    
    public Table<DataItem> DataItems
    {
        get
        {
            return this._dataItems;
        }
    }
    

    Tente "adiar" a instância de suas tabelas para quando elas forem acessadas, desta forma:

    private Table<DataItem> _dataItems;
    
    public Table<DataItem> DataItems
    {
        get
        {
            if (this._dataItems == null)
                this._dataItems = this.GetTable<DataItem>();
    
            return this._dataItems;
        }
    }
    
    public DataBaseContext(string connectionString)
        :base(connectionString)
    {
    
    }
    

    É possível que isso melhore sua performance.

    3 - A separação dos DataContext é uma excelente prática. Exemplo, se vc estiver trabalhando com um ERP, e separar os DataContext por departamento (RH, Contabilidade, Marketing, etc) é uma boa prática.

    4 - Faça experimentos criando os DataContexts manualmente, vc verá que ganhará melhor controle do código e ganhos de performance, segue exemplo de DataContext criado manualmente.

    public class DataBaseContext : DataContext 
    {
        public static string ConnectionString = "xpto";
    
        private Table<DataItem> _dataItems;
    
        public Table<DataItem> DataItems
        {
            get
            {
                if (this._dataItems == null)
                    this._dataItems = this.GetTable<DataItem>();
    
                return this._dataItems;
            }
        }
    
        public DataBaseContext(string connectionString)
            :base(connectionString)
        {
    
        }
    }
    

    Acho que algumas dicas aqui devem ajuda-lo a melhorar sua performance.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.wordpress.com/
    Twitter: @ferhenrique
    Thursday, October 20, 2011 12:44 PM
  • Olá Giovane,


    Acredito que não seja interessante a inclusão de uma camada usando WCF, pois vc irá criar mais uma camada em seu sistema, e continuará utilizando os mesmos datacontexs.

    O uso de WCF seria indicado se sua aplicação fosse desktop (WPF ou Windows Forms) e funcionasse fora do ambiente corporativo, fora do domínio ou fora da intranet.

    []s!

     


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.wordpress.com/
    Twitter: @ferhenrique
    Thursday, October 20, 2011 12:56 PM
  • Ola Fernando,

    Vou explicar como construí a arquitetura do sistema para um melhor entendimento. O sistema tem 10 projetos (9 base class projects e 1 interface Asp.net WebForms). Como havia necessidade de trafegar entre as camadas as entidades para ter uma melhor abstração dos projetos eu utilizei um projeto de controle do contexto (ObjectContextManager) após ler um excelente artigo de Jordan Van Gogh (http://dotnetslackers.com/articles/ado_net/managing-entity-framework-objectcontext-lifespan-and-scope-in-n-layered-asp-net-applications.aspx#managing-objectcontext-instantiation)

    O contexto é criado por requisição para manter uma integridade das ações e manipulações de dados. Após a request ser destruida o contexto também é destruído visando manter a performance da aplicação. Dessa forma, ao referenciar este projeto em minhas camadas consigo tansportar e trabalhar com as entidades sempre realizando um "call" do contexto de um único local. Utilizo a geração do EDMX de forma padrão exceto pelo fato dele separar o modelo EDMX do .cs model onde estão localizadas as entidades usando um template .tt. Tentei utlizar a geração de classes POCO mas não deu certo. Ocorreram problemas estranho e lentidão ao invez de ganho de performance.

    Exemplo de parte das entidades geradas:

     

    /// <summary>
        /// No Metadata Documentation available.
        /// </summary>
        [EdmEntityTypeAttribute(NamespaceName="Model", Name="Agencia")]
        [Serializable()]
        [DataContractAttribute(IsReference=true)]
        public partial class Agencia : EntityObject
        {
    #region Primitive Properties
        
            /// <summary>
            /// No Metadata Documentation available.
            /// </summary>
            [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
            [DataMemberAttribute()]
            public global::System.Int32 IDAgencia
            {
                get
                {
                    return _IDAgencia;
                }
                set
                {
                    if (_IDAgencia != value)
                    {
                        OnIDAgenciaChanging(value);
                        ReportPropertyChanging("IDAgencia");
                        _IDAgencia = StructuralObject.SetValidValue(value);
                        ReportPropertyChanged("IDAgencia");
                        OnIDAgenciaChanged();
                    }
                }
            }
    }
    

    O contexto é criado como abaixo (parte do código) Utilizando ObjectSet<>

    public partial class Entities : ObjectContext
        {
           // ...  Construtores
    /// <summary>
            /// No Metadata Documentation available.
            /// </summary>
            public ObjectSet<Agencia> Agencia
            {
                get
                {
                    if ((_Agencia == null))
                    {
                        _Agencia = base.CreateObjectSet<Agencia>("Agencia");
                    }
                    return _Agencia;
                }
            }
            private ObjectSet<Agencia> _Agencia;
    }
    

    Utilizo uma classe para extensões do contexto ObjectContextExtension.cs e nela tenho métodos para Update, Delete personalizados e comuns ao contexto para facilitar o trabalho de persistência de dados. Também utilizo o parther sugerido pelo Jordan para UnitOfWork onde as regras de negócio e manipulação dos cados é realizada na camanda de Business.

    Tenho conciência que a interface está defazada e pode ser melhorada sendo substituida por um novo projeto usando ASP.NET MVC + ExtJs (Projeto a ser desenvolvido para melhorida do sistema). A preocupação atual e principal é com o aumento do número de tabelas, consequentemente o tamanho do EDMX (modelo) e da inicialização do contexto.

    Como eu gero as views no momento de compilação e publicação do projeto. Eu reparei que ao realizar a PRIMEIRA query no sistema ela é extremamente lenta devido ao número de entidades no modelo. Criei uma lógica que só libera as requests para login quando o contexto é carregado. Isso foi criado porque mesmo que eu crie um contexto só para login, quando o usuário for carregar um devido módulo ele vai ter que esperar o contexto ser carregado, se não cai no mesmo problema de "First Access". Sem essa lógica, ficavam várias request presas quando o processo era restartado, reciclado ou desligado por qualquer motivo. Como os usuários tem que esperar pela lentidão da primeira query, ficavam várias resquests presas aguardando inicialização do contexto. Com essa lógica que desenvolvi, foi resolvido o problema de espera.

    A idéia de utlizar o WCF seria abstrair a camada de Entidades e dentro dela a camada de Business onde seria realizadas as regras de negócio e processamentos dos dados. Então com o WCF eu responderia para interface utlizando JSON caso adotasse a nova interface usando ASP.NET MVC 3 + Extjs trafegando somente JSON o que me trará uma ganho de performance muito grande.

     


    C#, asp.Net desenvolvedor

    • Edited by Giovane Dev Thursday, October 20, 2011 2:02 PM
    Thursday, October 20, 2011 1:59 PM
  • Caro Giovane,

    construi uma aplicação usando já tecnologia ASP MVC 3 e ExtJs.

    Estou bem contente com os resultados.

    Mas este problema que vc citou da demora, para mim é realmente um mistério.

    Fui recomendado a alterar meu contexto de forma a separar por módulos menores.

    Porém esta sua colocação a respeito dos requests é exatamente o meu problema interno.

    Minha equipe "perde" boa parte do seu tempo "aguardando" dezenas de testes rodarem por conta desta demora.

    Poderia me dizer onde posso encontrar documentação sobre esta sua solução.

    Desde já agradeço.

    Emerson. Atak Consultoria & Sistemas.


    atak

    Saturday, November 03, 2012 11:19 PM