none
Problemas utilizando C# 4 Capas RRS feed

  • Pregunta

  • Capa Entidad

    CAPA ENTIDADES public class EN_ESTUDIANTES { public string _Id_Estudiante { get; set; } } CAPA DATOS public class DA_ESTUDIANTES { CONEXION con = new CONEXION(); SqlDataAdapter da; SqlCommand cmd; DataTable dt; public DataTable Busqueda_Estudiante(EN_ESTUDIANTES EN_EST) { cmd = new SqlCommand("Select * From ESTUDIANTES_TABLA where Id_Estudiante LIKE @Id_Estudiante + '%' and Len(Num_Estudiante) < 8", con.cnn); cmd.Parameters.AddWithValue("@Id_Estudiane", EN_EST._Inicial ); da = new SqlDataAdapter(cmd); dt = new DataTable("ESTUDIANTES_TABLA"); da.Fill(dt); return dt; } } CAPA NEGOCIOS

    public string Busqueda_Estudiantes()
            {
                return  Busqueda_Estudiantes(); //No se si estoy escribiendo lo correcto//

            }

    QUIERO LLENAR CON LA CAPA DATOS  - Busqueda_Estudiantes un datagridview que se encuentra en un formulario que la CAPA PRESENTACION, El parametro en el formulario viene de un textbox llamado txtbusqueda, pero no que escribir en la CAPA NEGOCIOS para luego llamarlo del formulario que esta en la capa presentacion...


    lunes, 18 de junio de 2018 19:03

Respuestas

  • Hay una serie de errores en lo que nos presenta.  Le recomiendo buscar tutoriales de programación en capas.  Trataré de resumir algo aquí.

    Primero hay que definir las capas.  Normalmente se definen 3:  Acceso al almacén de datos; reglas de negocio; presentación.  En lo personal digo que falta una capa agnóstica entre el almacén de datos y las reglas de negocios para permitir inversión de control y fácil desacople entre el almacén de datos y las reglas de negocio.  Pero si la aplicación debe personalizarse para múltiples empresas con distintas reglas de negocio, una 5ta capa agnóstica entre las reglas de negocio y la de presentación es necesaria para lograr lo mismo:  Fácil desacople entre capas.  ¿Es esto lo que tiene usted?

    Luego necesita usted definir cómo va usted a mover los datos desde el almacén a la capa de reglas de negocio.  Normalmente la mayoría de la gente utiliza las clases que Entity Framework genera.  Yo no porque no suelo utilizar EF.  En su lugar, yo utilizo el patrón DTO con un objeto inspirado en IDictionary.  Pero puede omitir esto por ahora y utilizar las clases que representan los datos, a veces llamado el dominio.  El dominio define los objetos que modelan los datos almacenados en el almacén de datos, que suele ser una base de datos relacional pero puede ser cualquier cosa, en realidad.

    Cuando ya tiene la comunicación resuelta, la idea es que de alguna manera la capa de presentación solicita datos al almacén, que son de alguna manera arbitrados por las reglas de negocio.  Esta es la parte que muchos fallan:  Desde la capa de presentación acceden directamente al almacén.  Yo digo:  Si usamos el amacén directamente, la capa de reglas de negocio no tiene oportunidad de fiscalizar el acceso a datos.  Luego vienen preguntas como:  ¿Cómo puedo hacer que en mi programa solamente se lean XXX objetos que están asignados al usuario y que no pueda leer otros?  Y los programadores comienzan a escribir cosas como LINQ en la capa de presentación para empezar a implementar cosas como esta y más.  No.  Para la capa de presentación debería ser simple obtener datos, pero obtenerlos desde la capa de reglas de negocio donde se programan dichas cosas.

    Entonces, un ejemplo para usted.

    Capa de datos accede a datos de estudiantes.  Entonces en una capa aparte voy a definir la clase Estudiante (en singular, no es EstudianteS porque la clase represesnta un único estudiante; el plural se usa en variables que representan colecciones).  Yo he tratado de usar palabras clave en español, pero no me sale. :-(  Ignore mi americanismo de escribir nombres de clase y propiedades en inglés.

    namespace siglasProyecto.Domain
    {
        public class Student
        {
            //Idealmente en base de datos, los ID son siempre numéricos y IDENTITY.
            public long Id { get; set; }
            public string Name { get; set; }
        }
    }

    Su capa de datos tendría repositorios.  Normalmente un repositorio por tipo de objeto.  Yo siempre programo contra procedimientos almacenados, pero bueno.

    namespace siglasProyecto.sqldal
    {
        //Repositorio de estudiante.
        public class StudentRepository
        {
            #region Properties
            //Cadena de conexión obtenida en el constructor.
            private string ConnectionString { get; set; }
            #endregion
    
            #region Constructors
            public StudentRepository(string connString)
            {
                ConnectionString = connString;
            }
            #endregion
    
            #region Methods
            //Método para listar todos los estudiantes.
            public IList<Domain.Student> GetAll()
            {
                List<Domain.Student> students = new List<Domain.Student>();
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Select * From dbo.tblStudents", conn))
                    {
                        using (SqlDataReader r = cmd.ExecuteReader())
                        {
                            while (r.Read())
                            {
                                Student s = new Student()
                                {
                                    Id = (long)r["Id"],
                                    Name = r["Name"].ToString()
                                };
                                students.Add(s);
                            }
                        }
                    }
                }
                return students;
            }
    
            //Método que busca un estudiante por ID.
            public Domain.Student Get(long id)
            {
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Select * From dbo.tblStudents Where Id = @id", conn))
                    {
                        cmd.Parameters.Add("id", SqlDbType.BigInt).Value = id;
                        using (SqlDataReader r = cmd.ExecuteReader())
                        {
                            if (r.Read())
                            {
                                return new Student()
                                {
                                    Id = (long)r["Id"],
                                    Name = r["Name"].ToString()
                                };
                            }
                        }
                    }
                }
                //Si llegamos aquí, no hubo coincidencia por ID.
                return null;
            }
            #endregion
        }
    }

    Ahora ya tiene algo mejor.  Porque no tengo ideas de reglas de negocio en su aplicación, no le doy un ejemplo de cómo implementar relgas de negocio, pero en el peor de los casos, en las reglas de negocio debería usted tener un método que busca un estudiante por ID y otro que devuelve todos los estudiantes en la capa de reglas de negocio, que en el caso más simple, simplemente devuelve lo que devuelve el repositorio que se ve aquí arriba.  Si alguna vez se complica el asunto y hay que hacer algo más, pues ya tiene dónde hacerlo sin tocar el código de la capa de presentación.


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    lunes, 18 de junio de 2018 19:50
    Moderador
  • El KeyPress es mala idea porque no sabemos si el usuario se equivoca digitando, o si el ID es largo, etc.  Agregue un botón de Buscar y busque en el clic del botón.

    La capa de negocio, como lo dije, es en el más simple de los casos, un espejo de los repositorios de acceso a datos.  Yo no le compliqué el escenario, pero yo normalmente utilizo un DTO para transferir datos desde la capa de negocio a la capa de datos y vice versa.  En el ejemplo que puse utilizo las clases de dominio directamente, pero normalmente una capa de negocio extrae información de las clases de dominio y crea un DTO con esa información para transferirla a la capa de datos; también recibe DTO's desde la capa de datos de los cuales extrae información y con esa información crea objetos de las clases de dominio.

    Pero en fin, vuelvo al ejemplo.  Una clase de capa de negocio para estudiantes puede ser:

    namespace siglasProyecto.bl
    {
        public class StudentSource
        {
            #region Properties
            private sqldal.StudentRepository StudentRepository { get; set; }
            #endregion
    
            #region Constructors
            public StudentSource(string connString)
            {
                StudentRepository = new sqldal.StudentRepository(connString);
            }
            #endregion
    
            #region Methods
            public IList<Domain.Student> GetAll()
            {
                return StudentRepository.GetAll();
            }
    
            public Domain.Student Get(long id)
            {
                return StudentRepository.Get(id);
            }
            #endregion
        }
    }

    Y la capa de presentación instancia la clase StudentSource y de ella obtiene datos.  Esto quiere decir que en buena teoría estamos eliminando la necesidad de que la capa de presentación tenga que hacer referencia a la capa de acceso a datos.

    public class Form1 : Form
    {
        #region Properties
        private bl.StudentSource StudentSource { get; set; }
        private List<Domain.Student> AllStudents { get; set; }
        #endregion
    
        #region Constructors
        public Form1()
        {
            InitializeComponents();
        }
        #endregion
    
        #region Event Handlers
        private void Form1_Load(object sender, EventArgs e)
        {
            string cc = LeerCadenaDeConexionSQLdeAlgunaParte();
            StudentSource = new StudentSource(cc);
            //Llenamos la grilla con todos los estudiantes.
            AllStudents = StudentSource.GetAll();
            dataGridView1.DataSource = AllStudents;
        }
    
        private void Button1_Click(object sender, EventArgs e)
        {
            string sId = textBox1.Text;
            long id;
            if (!Int64.TryParse(sId, out id))
            {
                MessageBox.Show($"El texto de la casilla de búsqueda '{sId}' no puede interpretarse como un valor numérico.");
                return;
            }
            Domain.Student student = StudentSource.Get(id);
            if (student != null)
            {
                //Sí hubo coincidencia por ID.  Haga lo que quiera con él.
                ...
            }
        }
        #endregion
    }


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    • Marcado como respuesta Efrain Diaz lunes, 18 de junio de 2018 22:10
    lunes, 18 de junio de 2018 21:54
    Moderador

Todas las respuestas

  • Hay una serie de errores en lo que nos presenta.  Le recomiendo buscar tutoriales de programación en capas.  Trataré de resumir algo aquí.

    Primero hay que definir las capas.  Normalmente se definen 3:  Acceso al almacén de datos; reglas de negocio; presentación.  En lo personal digo que falta una capa agnóstica entre el almacén de datos y las reglas de negocios para permitir inversión de control y fácil desacople entre el almacén de datos y las reglas de negocio.  Pero si la aplicación debe personalizarse para múltiples empresas con distintas reglas de negocio, una 5ta capa agnóstica entre las reglas de negocio y la de presentación es necesaria para lograr lo mismo:  Fácil desacople entre capas.  ¿Es esto lo que tiene usted?

    Luego necesita usted definir cómo va usted a mover los datos desde el almacén a la capa de reglas de negocio.  Normalmente la mayoría de la gente utiliza las clases que Entity Framework genera.  Yo no porque no suelo utilizar EF.  En su lugar, yo utilizo el patrón DTO con un objeto inspirado en IDictionary.  Pero puede omitir esto por ahora y utilizar las clases que representan los datos, a veces llamado el dominio.  El dominio define los objetos que modelan los datos almacenados en el almacén de datos, que suele ser una base de datos relacional pero puede ser cualquier cosa, en realidad.

    Cuando ya tiene la comunicación resuelta, la idea es que de alguna manera la capa de presentación solicita datos al almacén, que son de alguna manera arbitrados por las reglas de negocio.  Esta es la parte que muchos fallan:  Desde la capa de presentación acceden directamente al almacén.  Yo digo:  Si usamos el amacén directamente, la capa de reglas de negocio no tiene oportunidad de fiscalizar el acceso a datos.  Luego vienen preguntas como:  ¿Cómo puedo hacer que en mi programa solamente se lean XXX objetos que están asignados al usuario y que no pueda leer otros?  Y los programadores comienzan a escribir cosas como LINQ en la capa de presentación para empezar a implementar cosas como esta y más.  No.  Para la capa de presentación debería ser simple obtener datos, pero obtenerlos desde la capa de reglas de negocio donde se programan dichas cosas.

    Entonces, un ejemplo para usted.

    Capa de datos accede a datos de estudiantes.  Entonces en una capa aparte voy a definir la clase Estudiante (en singular, no es EstudianteS porque la clase represesnta un único estudiante; el plural se usa en variables que representan colecciones).  Yo he tratado de usar palabras clave en español, pero no me sale. :-(  Ignore mi americanismo de escribir nombres de clase y propiedades en inglés.

    namespace siglasProyecto.Domain
    {
        public class Student
        {
            //Idealmente en base de datos, los ID son siempre numéricos y IDENTITY.
            public long Id { get; set; }
            public string Name { get; set; }
        }
    }

    Su capa de datos tendría repositorios.  Normalmente un repositorio por tipo de objeto.  Yo siempre programo contra procedimientos almacenados, pero bueno.

    namespace siglasProyecto.sqldal
    {
        //Repositorio de estudiante.
        public class StudentRepository
        {
            #region Properties
            //Cadena de conexión obtenida en el constructor.
            private string ConnectionString { get; set; }
            #endregion
    
            #region Constructors
            public StudentRepository(string connString)
            {
                ConnectionString = connString;
            }
            #endregion
    
            #region Methods
            //Método para listar todos los estudiantes.
            public IList<Domain.Student> GetAll()
            {
                List<Domain.Student> students = new List<Domain.Student>();
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Select * From dbo.tblStudents", conn))
                    {
                        using (SqlDataReader r = cmd.ExecuteReader())
                        {
                            while (r.Read())
                            {
                                Student s = new Student()
                                {
                                    Id = (long)r["Id"],
                                    Name = r["Name"].ToString()
                                };
                                students.Add(s);
                            }
                        }
                    }
                }
                return students;
            }
    
            //Método que busca un estudiante por ID.
            public Domain.Student Get(long id)
            {
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Select * From dbo.tblStudents Where Id = @id", conn))
                    {
                        cmd.Parameters.Add("id", SqlDbType.BigInt).Value = id;
                        using (SqlDataReader r = cmd.ExecuteReader())
                        {
                            if (r.Read())
                            {
                                return new Student()
                                {
                                    Id = (long)r["Id"],
                                    Name = r["Name"].ToString()
                                };
                            }
                        }
                    }
                }
                //Si llegamos aquí, no hubo coincidencia por ID.
                return null;
            }
            #endregion
        }
    }

    Ahora ya tiene algo mejor.  Porque no tengo ideas de reglas de negocio en su aplicación, no le doy un ejemplo de cómo implementar relgas de negocio, pero en el peor de los casos, en las reglas de negocio debería usted tener un método que busca un estudiante por ID y otro que devuelve todos los estudiantes en la capa de reglas de negocio, que en el caso más simple, simplemente devuelve lo que devuelve el repositorio que se ve aquí arriba.  Si alguna vez se complica el asunto y hay que hacer algo más, pues ya tiene dónde hacerlo sin tocar el código de la capa de presentación.


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    lunes, 18 de junio de 2018 19:50
    Moderador
  •  //Método que busca un estudiante por ID.
            public Domain.Student Get(long id)
            {
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Select * From dbo.tblStudents Where Id = @id", conn))
                    {
                        cmd.Parameters.Add("id", SqlDbType.BigInt).Value = id;
                        using (SqlDataReader r = cmd.ExecuteReader())
                        {
                            if (r.Read())
                            {
                                return new Student()
                                {
                                    Id = (long)r["Id"],
                                    Name = r["Name"].ToString()
                                };
                            }
                        }
                    }
                }
                //Si llegamos aquí, no hubo coincidencia por ID.
                return null;
            }
            #endregion
        }

    public class DA_ESTUDIANTES
        {
            CONEXION con = new CONEXION();
            SqlDataAdapter da;
            SqlCommand cmd;
            DataTable dt;
               
            public DataTable Busqueda_Estudiante(EN_ESTUDIANTES EN_EST)
            {
                    cmd = new SqlCommand("Select * From ESTUDIANTES_TABLA where Id_Estudiante LIKE @Id_Estudiante + '%' and Len(Num_Estudiante) < 8", con.cnn);
                    cmd.Parameters.AddWithValue("@Id_Estudiane", EN_EST._Inicial );
                    da = new SqlDataAdapter(cmd);
                    dt = new DataTable("ESTUDIANTES_TABLA");
                    da.Fill(dt);
                   return dt;
            }
        }

    Web jose la diferencia entre lo que me presenta y lo que yo tengo es que usted usa el datareader y yo uso el datatable, lo que necesito es que me diga como implementaria la CAPA NEGOCIOS y la CAPA PRESENTACION



    • Editado Efrain Diaz lunes, 18 de junio de 2018 21:05 FALTA
    lunes, 18 de junio de 2018 21:04
  • si tuviera en la Capa presentacion un datagridview1 y un textbox1 donde utilizando el keypress ponga el id y se presente en el datagridview eso es lo que necesito
    lunes, 18 de junio de 2018 21:13
  • El KeyPress es mala idea porque no sabemos si el usuario se equivoca digitando, o si el ID es largo, etc.  Agregue un botón de Buscar y busque en el clic del botón.

    La capa de negocio, como lo dije, es en el más simple de los casos, un espejo de los repositorios de acceso a datos.  Yo no le compliqué el escenario, pero yo normalmente utilizo un DTO para transferir datos desde la capa de negocio a la capa de datos y vice versa.  En el ejemplo que puse utilizo las clases de dominio directamente, pero normalmente una capa de negocio extrae información de las clases de dominio y crea un DTO con esa información para transferirla a la capa de datos; también recibe DTO's desde la capa de datos de los cuales extrae información y con esa información crea objetos de las clases de dominio.

    Pero en fin, vuelvo al ejemplo.  Una clase de capa de negocio para estudiantes puede ser:

    namespace siglasProyecto.bl
    {
        public class StudentSource
        {
            #region Properties
            private sqldal.StudentRepository StudentRepository { get; set; }
            #endregion
    
            #region Constructors
            public StudentSource(string connString)
            {
                StudentRepository = new sqldal.StudentRepository(connString);
            }
            #endregion
    
            #region Methods
            public IList<Domain.Student> GetAll()
            {
                return StudentRepository.GetAll();
            }
    
            public Domain.Student Get(long id)
            {
                return StudentRepository.Get(id);
            }
            #endregion
        }
    }

    Y la capa de presentación instancia la clase StudentSource y de ella obtiene datos.  Esto quiere decir que en buena teoría estamos eliminando la necesidad de que la capa de presentación tenga que hacer referencia a la capa de acceso a datos.

    public class Form1 : Form
    {
        #region Properties
        private bl.StudentSource StudentSource { get; set; }
        private List<Domain.Student> AllStudents { get; set; }
        #endregion
    
        #region Constructors
        public Form1()
        {
            InitializeComponents();
        }
        #endregion
    
        #region Event Handlers
        private void Form1_Load(object sender, EventArgs e)
        {
            string cc = LeerCadenaDeConexionSQLdeAlgunaParte();
            StudentSource = new StudentSource(cc);
            //Llenamos la grilla con todos los estudiantes.
            AllStudents = StudentSource.GetAll();
            dataGridView1.DataSource = AllStudents;
        }
    
        private void Button1_Click(object sender, EventArgs e)
        {
            string sId = textBox1.Text;
            long id;
            if (!Int64.TryParse(sId, out id))
            {
                MessageBox.Show($"El texto de la casilla de búsqueda '{sId}' no puede interpretarse como un valor numérico.");
                return;
            }
            Domain.Student student = StudentSource.Get(id);
            if (student != null)
            {
                //Sí hubo coincidencia por ID.  Haga lo que quiera con él.
                ...
            }
        }
        #endregion
    }


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    • Marcado como respuesta Efrain Diaz lunes, 18 de junio de 2018 22:10
    lunes, 18 de junio de 2018 21:54
    Moderador
  • Gracias
    lunes, 18 de junio de 2018 22:10
  • Yo lo hago asi:

    Capa de Datos

    namespace HistoriaClinica.Datos
    {
      public static class DAAlumno
      {
        public static DataTable GetAll()
        {
          using (SqlConnection cn = new SqlConnection(Conexion.StrCnn))
          {
            cn.Open();
            string sql = "SELECT * FROM Alumnos";
            DataTable dt = new DataTable();
            SqlCommand cmd = new SqlCommand(sql, cn);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);
            return dt;
          }
        }
    
        public static int GetNewIdDA()    {...}
        public static bool Update(Int32 Dni, String Apellido, String Nombres, Boolean Sexo)    {...}
        public static bool Insert(Int32 Dni, String Apellido, String Nombres, Boolean Sexo)    {... }
        public static bool Existe(Int32 Dni)   {...}
        public static bool Eliminar(Int32 Dni)    {....}
        }
    
    
      }
    }

    Capa de Negocios

      public sealed class BOAlumno
      {
    
    #region Constructores
    
        public BOAlumno()
        {
          Dni = -1;
        }
    
        public BOAlumno(DataRow r)
        {
          this.Dni = Conv.CInt(r["Dni"]);
          this.Apellido = Conv.CStr(r["Apellido"]);
          this.Nombres = Conv.CStr(r["Nombres"]);
          this.Sexo = Conv.CBool(r["Sexo"]);
        }
    
    #endregion
    
    #region Propiedades Publicas
    
        public Int32 Dni { get; set }
        public  String Apellido { get; set }
        public  String Nombres { get; set }
        public  Boolean Sexo { get; set }
       
    
    #endregion
    
    #region Metodos Publicos
    
        public bool Guardar()
        {
          bool rta = true;
          
          if (this.dni == -1) this.dni = DAAlumno.GetNewIdDA();
          return DAAlumno.Guardar(this.Dni, this.Apellido, this.Nombres, this.Sexo);
        }
    
        public bool Eliminar()
        {
          return DAAlumno.Eliminar(this.Dni);
        }
    
    #endregion
    
    #region Metodos Privados
    
    #endregion
      }
    

    A la capa de Negocios le agrego estas dos Clases:

    1- Clase Manager: de instancia única para inicializar colecciónes, crear instancias de objetos, etc.

    public class Manager
      {
    
    #region Constructores
    
        private static Manager instancia;
        public static Manager GetInstancia()
        {
        if (instancia == null)
          instancia = new Manager();
        return instancia;
        }
    
        private Manager()
        {
          CargarAlumnos();
        }
    
    #endregion Constructores
    
    #region Propiedades Publicas
    
        public List<BOAlumno> Alumnos { get; set; }
    
    #endregion Propiedades Publicas
    
    #region Metodos Privados (cargas)
    
        private void CargarAlumnos()
        {
          Alumnos = new List<BOAlumno>();
          DataTable t = Datos.DAAlumno.GetAll();
    
          if (t.Rows.Count > 0)
            foreach (DataRow r in t.Rows)
              Alumnos.Add(new BOAlumno(r));
        }
    
    #endregion Metodos Privados (cargas)
    
    #region Metodos Publicos (Búsquedas)
    
        public BOAlumno BuscarAlumno(Int32 dni)
        {
          BOAlumno rta;
          if((rta = Alumnos.Find(x=>x.Dni == dni)) == null)
            rta = new BOAlumno();
          return rta;
        }
    
    #endregion Metodos Publicos (Búsquedas)
    
      }

    2- Clase Conv para realizar conversiones y manejar datos Null.

     public static class Conv
      {
    
    #region int
    
        public static int CInt(object Nro)
        {
          return CInt(Nro, -1);
        }
    
        public static int CInt(object Nro, int ValorParaNulo)
        {
          int rta = ValorParaNulo;
          if (Nro != null)
            int.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion int
    
    #region Short
    
        public static short CShort(Object Nro)
        {
          return CShort(Nro, -1);
        }
    
        public static short CShort(Object Nro, short ValorParaNulo)
        {
          short rta = ValorParaNulo;
          if (Nro != null)
            short.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion Short, Int16
    
    #region long
    
        public static Int64 CLng(Object Nro)
        {
          return CLng(Nro,-1);
        }
    
        public static Int64 CLng(Object Nro, Int64 ValorParaNull)
        {
          Int64 rta = ValorParaNull;
          if (Nro != null)
            Int64.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion long
    
    #region byte
    
        public static byte CByte(Object Nro)
        {
          return CByte(Nro,0);
        }
    
        public static byte CByte(Object Nro, byte NumeroParaNul)
        {
          byte rta = NumeroParaNul;
          if (Nro != null)
            byte.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion byte
    
    #region byte[]
    
        public static byte[] CAbyte(Object ArrayBytes)
        {
          byte[] rta = new byte[0];
          if (ArrayBytes != DBNull.Value)
            rta = (byte[])ArrayBytes;
          return rta;
        }
    
        public static byte[] CAbyte(Object ArrayBytes, byte[] ArrayParaNul)
        {
          byte[] rta = ArrayParaNul;
          if (ArrayBytes != null)
            rta = (byte[])ArrayBytes;
          return rta;
        }
    
    #endregion byte[]
    
    #region float
    
        public static float CFloat(Object Nro)
        {
          return CFloat(Nro, -1f);
        }
        
        public static float CFloat(Object Nro, float ValorParaNull)
        {
          float rta = ValorParaNull;
          if (Nro != null)
            float.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion float
    
    #region double
    
        public static double CDbl(Object Nro)
        {
          return CDbl(Nro, -1);
        }
    
        public static double CDbl(Object Nro, Double ValorParaNull)
        {
          double rta = ValorParaNull;
          if (Nro != null)
            double.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion double
    
    #region Decimal
    
        public static Decimal  CDmal(Object Nro)
        {
          return CDmal(Nro, -1);
        }
    
        public static Decimal CDmal(Object Nro, Decimal ValorParaNull)
        {
          Decimal rta = ValorParaNull;
          if (Nro != null)
            Decimal.TryParse(Nro.ToString(), out rta);
          return rta;
        }
    
    #endregion Decimal
    
    #region char
    
        public static Char CChar(Object CaracterChar)
        {
          return CChar(CaracterChar, Char.MinValue);
        }
    
        public static Char CChar(Object CaracterChar, Char ValorParaNulo)
        {
          Char rta = ValorParaNulo;
          if (CaracterChar != null)
            Char.TryParse(CaracterChar.ToString(), out rta);
          return rta;
        }
    
    #endregion char
    
    #region bool
    
        public static bool CBool(Object ValorBool)
        {
          return CBool(ValorBool, false);
        }
    
        public static bool CBool(Object ValorBool, bool ValorParaNull)
        {
          bool rta = ValorParaNull;
          if (ValorBool != null)
            bool.TryParse(ValorBool.ToString(), out rta);
          return rta;
        }
    
    #endregion bool
    
    #region DateTime
    
        public static DateTime CDate(Object Fecha)
        {
          return CDate(Fecha, new DateTime(1900, 1, 1));
        }
    
        public static DateTime CDate(Object Fecha, DateTime FechaParaNull)
        {
          DateTime rta = FechaParaNull;
          if (Fecha != null && Fecha.ToString().Trim() != "") //Si el valor de Fechas="", TryParse la convierten en DateTime.MinValue y da error en ciertos controles
            DateTime.TryParse(Fecha.ToString(), out rta);
          return rta;
        }
    
    #endregion DateTime
    
    #region String
    
        public static String CStr(Object ValorString)
        {
          return CStr(ValorString, String.Empty);
        }
    
        public static String CStr(Object ValorString, String ValorParaNull)
        {
          string rta = ValorParaNull;
          if (ValorString != null)
            rta = ValorString.ToString();
          return rta;
        }
    
    #endregion String
    
    
    #region Metodos sobrecargados o auxiliares
    
        #region cInt16
    
        public static short CInt16(Object Nro)
        {
          return CShort(Nro, -1);
        }
    
        public static short CInt16(Object Nro, short ValorParaNulo)
        {
          return CShort(Nro, ValorParaNulo);
        }
    
        #endregion cInt16
    
        #region int32
    
        public static int CInt32(object Nro)
        {
          return CInt(Nro, -1);
        }
    
        public static int CInt32(object Nro, int ValorParaNulo)
        {
          return CInt(Nro, ValorParaNulo);
        }
    
        #endregion int32
    
        #region Int64
    
        public static Int64 CInt64(Object Nro)
        {
          return CLng(Nro,-1);
        }
    
        public static Int64 CInt64(Object Nro, Int64 ValorParaNull)
        {
          return CLng(Nro, ValorParaNull);
        }
    
        #endregion Int64
    
        #region Single
    
        public static float CSgl(Object Nro)
        {
          return CFloat(Nro, -1f);
        }
    
        public static float CSgl(Object Nro, float ValorParaNull)
        {
          return CFloat(Nro, ValorParaNull);
        }
    
        #endregion Single
    
        #region Boolean
    
        public static bool CBoolean(Object ValorBool)
        {
          return CBool(ValorBool, false);
        }
    
        public static bool CBoolean(Object ValorBool, bool ValorParaNull)
        {
          return CBool(ValorBool, ValorParaNull);
        }
    
        #endregion Boolean
    
    #endregion Metodos sobrecargados o auxiliares   
      }

    Capa de Presentacion

    ublic partial class Principal : Form
      {
        private Manager Mg = Manager.GetInstancia();
        private List<BOAlumno> Alumnos;
        BindingSource bsAlumnos = new BindingSource();
    
        public Principal()
        {
          InitializeComponent();
        }
    
        private void Principal_Load(object sender, EventArgs e)
        {
          grAlumnos.AutoGenerateColumns = false;
          RecargarAlumnos();
        }
    
        private void RecargarAlumnos()
        {
          Alumnos = Mg.Alumnos;
          bsAlumnos.DataSource = Alumnos;
          grAlumnos.DataSource = bsAlumnos;
        }
    
    
        private void txtDniB_TextChanged(object sender, EventArgs e)
        {
          int dni = -2;
          if (int.TryParse(StrDni, out dni))
          {
            bsAlumnos.DataSource = Alumnos.Where(x => x.Dni.ToString().StartsWith(StrDni));
            bsAlumnos.ResetBindings(false);
          }
          else if (StrDni == "")
          {
            bsAlumnos.DataSource = Alumnos;
            bsAlumnos.ResetBindings(false);
          }
        }
    
        private void txtApyNomB_TextChanged(object sender, EventArgs e)
        {
          if (txtApyNomB.Text == "")
            bsAlumnos.DataSource = Alumnos;
          else
          {
            List<BOAlumno> filtro = Alumnos.Where(x => x.ApyNom.ToLower().StartsWith(txtApyNomB.Text.ToLower())).ToList<BOAlumno>();
            bsAlumnos.DataSource = filtro;
          }
            
          bsAlumnos.ResetBindings(false);
        }
    
        private void btnGuardar_Click(object sender, EventArgs e)
        {
          BOAlumno aAct;
          if ((aAct = (BOAlumno)grAlumnos.CurrentRow.DataBoundItem) == null)
          {
            MessageBox.Show("No Hay nadie seleccionado", "GUARDAR DATOS", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
          }
         
          if (aAct.Guardar())
            MessageBox.Show("Actualizado", "GUARDAR DATOS", MessageBoxButtons.OK, MessageBoxIcon.Information);
          else
            MessageBox.Show("No se pudo Actualizar", "GUARDAR DATOS", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
      }
    

    Esto funciona pero entiendo que, seguramente no se ajusta a lo que las buenas prácticas de programación recomiendas. Así que, bienvenida toda crítica.

    Saludos


    lunes, 18 de junio de 2018 22:52