none
DataContext, classes diferentes para mesma tabela RRS feed

  • Pergunta

  • Olá,

    a muito tempo atrás já tinha perguntado sobre o isto, e naquele momento o problema foi resolvido.
    Porém, fui atrás do post, e meu problema persiste, e vou mostrar aqui a situação:

    Tenho o meu Context:

    public class ERPCodeFirstContext : DbContext
        {
            public DbSet<Usuario> Usuario { get; set; }                
    
            public ERPCodeFirstContext()
            {
                Database.SetInitializer<ERPCodeFirstContext>(null);            
            }       
    		
    		protected override void OnModelCreating(DbModelBuilder modelBuilder)
    		{
                var _DBOwner = "dbo";
    
                modelBuilder.Entity<Usuario>().ToTable("Usuario", schemaName: _DBOwner);            
    
    		}
    	}

    Ele tem o DBSet para Usuario, e está mapeado para usar a tabela Usuario no banco de dados.

    Agora vem meu problema, tenho 5 classes para usuários, uma para validar, outra para que o cara esqueceu a senha e outra para ativação (que esta salva o campo DtAtivação) do usuário.

    Porém como o DBSet está ligado com a classe Usuario, ao buscar os dados e alterar a DtAtivacao para um valor e tentar salvar, dá erro que alguns campos não foram informados.
    Pois esta classe é usada para inserir um novo usuário.

    Minha dúvida é, como sair desta sinuca de bico? Tem que criar 2 DBSet para a mesma tabela?
    Ou criar uma super classe SuperUsuario e lá dentro vincular as outras classes?

        public class UsuarioEsqueci
        {
            [Display(Name = "Login")]
            public string Login { get; set; }
            [Display(Name = "Senha")]
            public string Email { get; set; }
        }
    
        public class UsuarioConectar
        {
            [Required(ErrorMessage = "Obrigatório")]
            [Display(Name = "Login")]                
            public string Login { get; set; }
    
            [Required(ErrorMessage = "Obrigatório")]
            [DataType(DataType.Password)]                
            [Display(Name="Senha")]
            public string Senha { get; set; }
        }
    
        public class UsuarioAtivacao
        {
            [Key]
            public int UsuarioID { get; set; }
            public string Login { get; set; }
            public string Chave { get; set; }
            public Nullable<DateTime> DtAtivacao { get; set; }
        }
    
        public class Usuario
        {
            [Key]
            public int UsuarioID { get; set; }
    
            public int PessoaID { get; set; }
    
            [Required(ErrorMessage = "Campo 'Nome' é obrigatório")]
            [Display(Name = "Login")]        
            public string Login { get; set; }
            
            [Required(ErrorMessage = "Campo 'E-mail' é obrigatório")]
            [Display(Name = "E-mail")]        
            [DataType(DataType.EmailAddress)]
            [ERP.Helpers.Validacoes.Email]
            [NotMapped]
            public string Email { get; set; }
    
            [Required(ErrorMessage = "Campo 'Confirme E-mail' é obrigatório")]
            [Display(Name = "Confirme E-mail")]
            [Compare("Email", ErrorMessage = "O 'e-mail' e a 'confirme o  e-mail' não estão iguais")]
            [DataType(DataType.EmailAddress)]
            [ERP.Helpers.Validacoes.Email]
            [NotMapped]
            public string ConfirmeEmail { get; set; }
    
            [Required(ErrorMessage = "Campo 'Nome' é obrigatório")]
            [Display(Name = "Nome")]        
            public string Nome { get; set; }
            
            [Required(ErrorMessage = "Campo 'Senha' é obrigatório")]
            [Display(Name = "Senha")]
            [StringLength(50, ErrorMessage = "A {0} deve ter {2} caracteres no mínimo", MinimumLength = 6)]
            [DataType(DataType.Password)]        
            public string Senha { get; set; }
    
            [Required(ErrorMessage = "Campo 'Confirme a senha' é obrigatório")]        
            [Display(Name = "Confirme a senha")]
            [Compare("Senha", ErrorMessage = "A 'senha' e a 'confirme a senha' não estão iguais")]
            [DataType(DataType.Password)]
            [NotMapped]
            public string ConfirmeSenha { get; set; }
                    
            public string Chave { get; set; }
            public Nullable<DateTime> DtAtivacao { get; set; }
            public string Gestor { get; set; }
            public string GestorVisao { get; set; }
            public string UsuarioExtra { get; set; }
    
            [Required(ErrorMessage = "Campo 'Tipo de pessoa' é obrigatório")]
            [Display(Name = "Tipo de pessoa")]
            [NotMapped]
            public int TipoPessoaID { get; set; }
    
            [Required(ErrorMessage = "Campo 'Sexo' é obrigatório")]
            [Display(Name = "Sexo")]        
            [ERP.Helpers.Validacoes.CompareValuesAttribute("TipoPessoaID")]
            [NotMapped]
            public int SexoID { get; set; }
            
            public int EmpresaID { get; set; }
            public string Fixo { get; set; }
            public string Status { get; set; }
            public string Apagado { get; set; }
            public Nullable<DateTime> DtApagado { get; set; }
            public int UsuCad { get; set; }
            public DateTime DtCad { get; set; }
            public int UsuAlt { get; set; }
            public DateTime DtAlt { get; set; }
            public int UsuUltAlt { get; set; }
            public DateTime DtUltAlt { get; set; }
        }    
    

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    quarta-feira, 3 de outubro de 2012 13:15

Respostas

  • Oi Marlon,

    Sobre previsão para resolução deste problema é difícil falar.

    Neste caso, o recomendado é criar outro DbContext, que mapeie outra classe (se vc estivesse utilizando Fluent API não precisaria de outra classe) com apenas os campos que quer atualizar para essa tabela.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    • Marcado como Resposta Marlon Tiedt sexta-feira, 5 de outubro de 2012 11:24
    quarta-feira, 3 de outubro de 2012 13:53
    Moderador

Todas as Respostas

  • Olá Marlon,

    Neste caso vc pode tentar indicar para o EF que vc quer apenas fazer o UPDATE de um único campo.

    Veja o exemplo abaixo:

    public void ChangePassword(int userId, string password)
    {
      var user = new User() { Id = userId, Password = password };
      using (var db = new MyEfContextName())
      {
        db.Users.Attach(user);
        db.Entry(user).Property(x => x.Password).IsModified = true;
        db.SaveChanges();
      }
    }

    A propriedade Password será a única modificada.

    Veja se isso atende o seu problema.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    quarta-feira, 3 de outubro de 2012 13:29
    Moderador
  • Olá Fernando,

    o sistema ainda reclama que está faltando campos obrigatórios...


    var user = new Usuario() { UsuarioID = dados.UsuarioID, DtAtivacao = DateTime.Now };
    db.Usuario.Attach(user);
    db.Entry(user).Property(x => x.DtAtivacao).IsModified = true;
    db.SaveChanges();

    Abs

    Marlon Tiedt
    www.sesmt.com.br


    • Editado Marlon Tiedt quarta-feira, 3 de outubro de 2012 13:39
    quarta-feira, 3 de outubro de 2012 13:38
  • Putz...

    Isso é muito chato... outro dia li um e-mail de alguns Data Insiders reclamando justamente disso... mesmo marcando só algumas propriedades para serem salvas na base de dados, a validação acontecia para todas as propriedades.

    Marlon, neste caso, acredito que o jeito mais rápido e fácil de resolver esta questão seja criar uma procedure que faça essa atualização e fazer o EF executá-la...

    Acredito que este seja um bug que será corrigido nas próximas versões.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    quarta-feira, 3 de outubro de 2012 13:41
    Moderador
  • Ou fazer o SQL na mão mesmo...
    Que droga...

    Será que tem previsão deste bug ser resolvido?

    Abs

    Marlon Tiedt
    www.sesmt.com.br

    quarta-feira, 3 de outubro de 2012 13:48
  • Oi Marlon,

    Sobre previsão para resolução deste problema é difícil falar.

    Neste caso, o recomendado é criar outro DbContext, que mapeie outra classe (se vc estivesse utilizando Fluent API não precisaria de outra classe) com apenas os campos que quer atualizar para essa tabela.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    • Marcado como Resposta Marlon Tiedt sexta-feira, 5 de outubro de 2012 11:24
    quarta-feira, 3 de outubro de 2012 13:53
    Moderador
  • Que droga...

    Um trampo ferrado para algo tão simples...
    Mas valeu...

    Abs

    Marlon Tiedt
    www.sesmt.com.br

    quarta-feira, 3 de outubro de 2012 14:06
  • Olá Fernando,

    pensando em ter 2 DBContext, esta forma abaixo está correta, ou preciso fazer 2 strings de conexão?

    public class ERPContext : DbContext
    {
        public DbSet<UsuarioAtivacao> UsuarioAtivacao { get; set; }
    
        public ERPContext()
        {
            Database.SetInitializer<ERPCodeFirstContext>(null);            
        }       
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
            var _DBOwner = "dbo";
            modelBuilder.Entity<UsuarioAtivacao>().ToTable("Usuario", schemaName: _DBOwner);       
        }
    
    }

    DBContext original:

    public class ERPCodeFirstContext : DbContext
    {
      public DbSet<Usuario> Usuario { get; set; }
      
      public ERPCodeFirstContext()
      {
          Database.SetInitializer<ERPCodeFirstContext>(null);            
      }       
    
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          var _DBOwner = "dbo";
    
          modelBuilder.Entity<Usuario>().ToTable("Usuario", schemaName: _DBOwner);          
      }
    }

    WebConfig:

     <add name="ERPCodeFirstContext" connectionString="Data Source=E020\SQLExpress;Initial Catalog=ERP;User ID=ERP; Password=testes" providerName="System.Data.SqlClient" />
        
    

    Abs

    Marlon Tiedt
    www.sesmt.com.br

    quarta-feira, 3 de outubro de 2012 14:53
  • Oi Marlon,

    Pode ter uma única string de conexão ;)

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    quarta-feira, 3 de outubro de 2012 14:55
    Moderador