Introducción
El objetivo de este articulo será reflejar los siguiente puntos:
- Grabar una imagen en un campo de una base de datos
- Recuperar la imagen visualizándola en un celda del DataGridView y en un PictureBox
- Comunicar un formulario pasándole información en el constructor para la edición de una entidad
- Detectar el cierre del formulario para actualizar la información de los empleados
Dominio de la aplicación
Bien empezaremos definiendo al estructura de datos de la aplicación.
El dominio consiste en Empleados, con información básica del mismo, mas un campo de imagen el cual es opcional por lo cual esta marcado para permitir nulos.
El atributo Estado Civil tomara los valores de 1 a 4, los cuales fueron definido en un enumerado.
Adicionalmente el empleado podrá tener Estudios realizados, los cuales se asignan marcando de una lista.
El diseño de la interfaz es simple, un formulario principal que lista los usuarios.
Y otro que edita el usuario cuando se realiza un doble click en la fila de la lista.
La arquitectura de la aplicación es en dos capas, la presentación se comunica con DataAccess pasándole la información que necesita persistir o recuperar, el medio de comunicación son entidades definidas por medio de clases que modelan el dominio de la aplicación.
Si bien el esquema de estas entidades son muy parecido al de la base de datos ,se debe apreciar que la entidad “Empleado” posee una relación con la de estudios, lo cual posibilita la navegación de la información asociada.
Cargar lista de empleados (con imágenes)
En esta sección analizaremos como cargar las imágenes en el DataGridView, tomando esta información desde la base de datos.
El primer paso será recuperar los registros de la tabla, incluyendo la imagen.
[C#]
public static List<EmpleadoEntity> ObtenerTodos() { List<EmpleadoEntity> lista = new List<EmpleadoEntity>(); using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString())) { conn.Open(); string query = @"SELECT IdEmpleado, Nombre, Apellido, FechaNacimiento, EstadoCivil, Imagen FROM Empleados"; SqlCommand cmd = new SqlCommand(query, conn); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { lista.Add(ConvertirEmpleado(reader, false)); } } return lista; } private static EmpleadoEntity ConvertirEmpleado(IDataReader reader, bool cargarRelaciones) { EmpleadoEntity empleado = new EmpleadoEntity(); empleado.IdEmpleado = Convert.ToInt32(reader["IdEmpleado"]); empleado.Nombre = Convert.ToString(reader["Nombre"]); empleado.Apellido = Convert.ToString(reader["Apellido"]); empleado.FechaNacimiento = Convert.ToDateTime(reader["FechaNacimiento"]); empleado.EstadoCivil = Convert.ToInt16(reader["EstadoCivil"]); if (reader["Imagen"] != DBNull.Value) empleado.Imagen = (byte[])reader["Imagen"]; if (cargarRelaciones) { empleado.Estudios = EstudiosDAL.ObtenerAsignadoEmpleado(empleado.IdEmpleado); } return empleado; }
[VB.NET]
Public Shared Function ObtenerTodos() As List(Of EmpleadoEntity) Dim lista As New List(Of EmpleadoEntity)() Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString()) conn.Open() Dim query As String = "SELECT IdEmpleado, Nombre, Apellido, FechaNacimiento, EstadoCivil, Imagen" & _ "FROM Empleados" Dim cmd As New SqlCommand(query, conn) Dim reader As SqlDataReader = cmd.ExecuteReader() While reader.Read() lista.Add(ConvertirEmpleado(reader, False)) End While End Using Return lista End Function Private Shared Function ConvertirEmpleado(ByVal reader As IDataReader, ByVal cargarRelaciones As Boolean) As EmpleadoEntity Dim empleado As New EmpleadoEntity() empleado.IdEmpleado = Convert.ToInt32(reader("IdEmpleado")) empleado.Nombre = Convert.ToString(reader("Nombre")) empleado.Apellido = Convert.ToString(reader("Apellido")) empleado.FechaNacimiento = Convert.ToDateTime(reader("FechaNacimiento")) empleado.EstadoCivil = Convert.ToInt16(reader("EstadoCivil")) If reader("Imagen") IsNot DBNull.Value Then empleado.Imagen = DirectCast(reader("Imagen"), Byte()) End If If cargarRelaciones Then empleado.Estudios = EstudiosDAL.ObtenerAsignadoEmpleado(empleado.IdEmpleado) End If Return empleado End Function
Es preciso notar como se asigna la imagen a la entidad
[C#]
if (reader["Imagen"] != DBNull.Value) empleado.Imagen = (byte[])reader["Imagen"];
[VB.NET]
If reader("Imagen") IsNot DBNull.Value Then empleado.Imagen = DirectCast(reader("Imagen"), Byte()) End If
lo cual resulta muy simple.
En el formulario “ListaEmpleados” se usa esta información para cargar el DataGridView
[C#]
private void CargarListaEmpleados() { dgvEmpleados.AutoGenerateColumns = false; dgvEmpleados.DataSource = EmpleadosDAL.ObtenerTodos(); foreach (DataGridViewRow row in dgvEmpleados.Rows) { //se asigna el alto de la fila para poder ver la imagen correctamente row.Height = 120; //se recupera la entidad que es asignada como dato EmpleadoEntity empleado = row.DataBoundItem as EmpleadoEntity; if (empleado.Imagen == null) row.Cells["Imagen"].Value = ImageHelper.ObtenerImagenNoDisponible(); else row.Cells["Imagen"].Value = ImageHelper.ByteArrayToImage(empleado.Imagen); } }
[VB.NET]
Private Sub CargarListaEmpleados() dgvEmpleados.AutoGenerateColumns = False dgvEmpleados.DataSource = EmpleadosDAL.ObtenerTodos() For Each row As DataGridViewRow In dgvEmpleados.Rows 'se asigna el alto de la fila para poder ver la imagen correctamente row.Height = 120 'se recupera la entidad que es asignada como dato Dim empleado As EmpleadoEntity = TryCast(row.DataBoundItem, EmpleadoEntity) If empleado.Imagen Is Nothing Then row.Cells("Imagen").Value = ImageHelper.ObtenerImagenNoDisponible() Else row.Cells("Imagen").Value = ImageHelper.ByteArrayToImage(empleado.Imagen) End If Next End Sub
seguramente una pregunta que se hagan es porque en este método se esta recorriendo las filas del DataGridView después de asignar los datos al mismo ?
bien esto tiene una explicación, resulta que la celda de imagen del DataGridView requiere un tipo Image para poder trabajar, pero la entidad que proporcionamos devuelve un array de byte, lo cual no es compatible, entonces es que se aprovecha la capacidad del DataGridView para retornar la entidad que bindea a cada fila para obtener la entidad “Empleado” y convertir el array de byte al tipo Image.
También debo aclara que esto se intento hacer en un evento, como ser el CellFormatting, pero resulto un desastre porque este evento repintaba constantemente la información generando un parpadeo molesto en el control, se podría haber realizado esto mismo en el evento DataBindingComplete, pero para este caso no valía la pena separa la funcionalidad, por eso se dejo allí mismo.
En ese método se hace uso del la funcionalidad de “helper” que no es mas que un grupo de funciones que facilitan ciertas tareas, en este caso convierten el array de byte en Image.
Comunicar Formulario y detectar cierre del form hijo
Al realizar un doble click en la celda del DataGridView este entra en modo edición, esto implica simplemente toma la información y pacérsela al formulario
Desde “ListaEmpleados” se trabaja con el evento tomando solo el id del empleado, y en la instancia del formulario se lo pasa en el constructor. También en la misma operación se adjunta el evento FormClosing para poder detectar el cierre el form y proceder a la actualización del la lista de empleados.
[C#]
private void dgvEmpleados_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) { int IdEmpleado = Convert.ToInt32(dgvEmpleados.Rows[e.RowIndex].Cells["IdEmpleado"].Value); // // al pasarle un id de empleado este lo cargara para su edicion // EditarEmpleado frmEditar = new EditarEmpleado(IdEmpleado); frmEditar.FormClosing += new FormClosingEventHandler(frmEditar_FormClosing); frmEditar.Show(); } void frmEditar_FormClosing(object sender, FormClosingEventArgs e) { // // al cerrarse el form de edicion se ingresa a este evento // para actualizar la informacion del listado // EditarEmpleado frmEdit = sender as EditarEmpleado; if(frmEdit.DialogResult == DialogResult.OK) CargarListaEmpleados(); }
[VB.NET]
Private Sub dgvEmpleados_CellContentDoubleClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Dim IdEmpleado As Integer = Convert.ToInt32(dgvEmpleados.Rows(e.RowIndex).Cells("IdEmpleado").Value) ' ' al pasarle un id de empleado este lo cargara para su edicion ' Dim frmEditar As New EditarEmpleado(IdEmpleado) AddHandler frmEditar.FormClosing, New FormClosingEventHandler(AddressOf frmEditar_FormClosing) frmEditar.Show() End Sub Private Sub frmEditar_FormClosing(sender As Object, e As FormClosingEventArgs) ' ' al cerrarse el form de edicion se ingresa a este evento ' para actualizar la informacion del listado ' Dim frmEdit As EditarEmpleado = TryCast(sender, EditarEmpleado) If frmEdit.DialogResult = DialogResult.OK Then CargarListaEmpleados() End If End Sub
En el formulario que recibe esta información “EditarEmpleado” solo utiliza el id del empleado, porque con este ira a la db y recuperara la entidad para cargar el formulario, no hace falta enviar la entidad completa, solo la mínima información como para que este form pueda recuperar el resto.
[C#]
public partial class EditarEmpleado : Form { private int? _idEmpleado = null; public EditarEmpleado() { InitializeComponent(); } public EditarEmpleado(int idEmpleado) : this() { _idEmpleado = idEmpleado; } . . . }
[VB.NET]
Public Partial Class EditarEmpleado Inherits Form Private _idEmpleado As Nullable(Of Integer) = Nothing Public Sub New() InitializeComponent() End Sub Public Sub New(idEmpleado As Integer) Me.New() _idEmpleado = idEmpleado End Sub . . . End Class
Cuando se termina la edición se retorna como un resultado del formulario que indicara si se grabo o se cancelo el formulario, esto se logra por medio del DialogResult.
[C#]
private void btnGuardar_Click(object sender, EventArgs e) { . . . // // se graba // EmpleadosDAL.Save(empleado); this.DialogResult = DialogResult.OK; this.Close(); } private void btnCancelar_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; this.Close(); }
[VB.NET]
Private Sub btnGuardar_Click(sender As Object, e As EventArgs) . . . ' ' se graba ' EmpleadosDAL.Save(empleado) Me.DialogResult = DialogResult.OK Me.Close() End Sub Private Sub btnCancelar_Click(ByVal sender As Object, ByVal e As EventArgs) Me.DialogResult = DialogResult.Cancel Me.Close() End Sub
Editar Empleado (mostrando la imagen en un Picturebox)
Esta tarea es bastante simple, solo implica recuperar una entidad en concreto haciendo uso de la cada de datos y cargar la entidad en los controles para presentar esta al usuario.
[C#]
public static EmpleadoEntity ObtenerById(int idEmpleado) { EmpleadoEntity empleado = null; using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString())) { conn.Open(); string query = @"SELECT IdEmpleado, Nombre, Apellido, FechaNacimiento, EstadoCivil, Imagen FROM Empleados WHERE IdEmpleado = @idEmpleado"; SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@idEmpleado", idEmpleado); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { empleado = ConvertirEmpleado(reader, true); } } return empleado; }
[VB.NET]
Public Shared Function ObtenerById(ByVal idEmpleado As Integer) As EmpleadoEntity Dim empleado As EmpleadoEntity = Nothing Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString()) conn.Open() Dim query As String = "SELECT IdEmpleado, Nombre, Apellido, FechaNacimiento, EstadoCivil, Imagen " & _ "FROM Empleados WHERE IdEmpleado = @idEmpleado" Dim cmd As New SqlCommand(query, conn) cmd.Parameters.AddWithValue("@idEmpleado", idEmpleado) Dim reader As SqlDataReader = cmd.ExecuteReader() If reader.Read() Then empleado = ConvertirEmpleado(reader, True) End If End Using Return empleado End Function
Una vez que se tiene la entidad solo se carga esta en los contoles.
[C#]
private void EditarEmpleado_Load(object sender, EventArgs e) { CargarEstadoCivil(); CargarEstudio(); //por defecto se carga una imagen de no disponible picImagenEmpleado.Image = ImageHelper.ObtenerImagenNoDisponible(); // // se carga la informacion del empleado que se quiere editar // if (_idEmpleado.HasValue) { EmpleadoEntity empleado = EmpleadosDAL.ObtenerById(_idEmpleado.Value); _idEmpleado = empleado.IdEmpleado; txtNombre.Text = empleado.Nombre; txtApellido.Text = empleado.Apellido; dtpFechaNacimiento.Value = empleado.FechaNacimiento; cbEstadoCivil.SelectedValue = Convert.ToInt32(empleado.EstadoCivil); if (empleado.Imagen == null) picImagenEmpleado.Image = ImageHelper.ObtenerImagenNoDisponible(); else picImagenEmpleado.Image = ImageHelper.ByteArrayToImage(empleado.Imagen); // // Se obtienen los estudios del empleado // AsignarEstudios(empleado); } } private void CargarEstadoCivil() { cbEstadoCivil.DisplayMember = "Descripcion"; cbEstadoCivil.ValueMember = "IdEstadoCivil"; cbEstadoCivil.DataSource = EstadoCivilDAL.ObtenerTodos(); } private void CargarEstudio() { dgvEstudios.AutoGenerateColumns = false; dgvEstudios.DataSource = EstudiosDAL.ObtenerTodos(); } private void AsignarEstudios(EmpleadoEntity empleado) { List<DataGridViewRow> rows = (from row in dgvEstudios.Rows.Cast<DataGridViewRow>() let idEstudio = Convert.ToInt32(row.Cells["IdEstudio"].Value) join dd in empleado.Estudios on idEstudio equals dd.IdEstudio select row).ToList(); rows.ForEach(o => o.Cells["Seleccion"].Value = true); }
[VB.NET]
Private Sub EditarEmpleado_Load(ByVal sender As Object, ByVal e As EventArgs) CargarEstadoCivil() CargarEstudio() 'por defecto se carga una imagen de no disponible picImagenEmpleado.Image = ImageHelper.ObtenerImagenNoDisponible() ' ' se carga la informacion del empleado que se quiere editar ' If _idEmpleado.HasValue Then Dim empleado As EmpleadoEntity = EmpleadosDAL.ObtenerById(_idEmpleado.Value) _idEmpleado = empleado.IdEmpleado txtNombre.Text = empleado.Nombre txtApellido.Text = empleado.Apellido dtpFechaNacimiento.Value = empleado.FechaNacimiento cbEstadoCivil.SelectedValue = Convert.ToInt32(empleado.EstadoCivil) If empleado.Imagen Is Nothing Then picImagenEmpleado.Image = ImageHelper.ObtenerImagenNoDisponible() Else picImagenEmpleado.Image = ImageHelper.ByteArrayToImage(empleado.Imagen) End If ' ' Se obtienen los estudios del empleado ' AsignarEstudios(empleado) End If End Sub Private Sub CargarEstadoCivil() cbEstadoCivil.DisplayMember = "Descripcion" cbEstadoCivil.ValueMember = "IdEstadoCivil" cbEstadoCivil.DataSource = EstadoCivilDAL.ObtenerTodos() End Sub Private Sub CargarEstudio() dgvEstudios.AutoGenerateColumns = False dgvEstudios.DataSource = EstudiosDAL.ObtenerTodos() End Sub Private Sub AsignarEstudios(empleado As EmpleadoEntity) Dim rows As List(Of DataGridViewRow) = (From row In dgvEstudios.Rows.Cast(Of DataGridViewRow)() _ Let idEstudio = Convert.ToInt32(row.Cells("IdEstudio").Value) _ Join dd In empleado.Estudios On idEstudio Equals dd.IdEstudio _ Select row).ToList() 'rows.ForEach(Function(o) o.Cells("Seleccion").Value = True) rows.ForEach(Function(o) InlineAssignHelper(o.Cells("Seleccion").Value, True)) End Sub
La asignación de la imagen es muy simple y similar a como se trabajo en el DataGridview, solo se convierte el array de byte recuperado de la tabla en la base de datos y se carga directo en el PictureBox.
Algo interesante a remarcar es la forma en como se carga la lista de Estudios, en esta se usan dos consultas separadas, por un lado la primera que carga todos los estudios existentes, si se ingresara en modo de alta de empleado solo esta lista seria cargada, pero si se esta editando se recupera la lista de estudios asignados a ese empleado en particular y por medio de una consulta linq (método AsignarEstudios) se realiza la unión entres ambas listas aquellas filas del DataGridView que coincidan serán marcadas porque son las que el empleado tiene registradas en la tabla.
Búsqueda de una imagen (cargar archivo a un PictureBox)
Un punto que debería ser menor pero que he visto con mucha dificultad en preguntas en los foros, es como cargar seleccionar un archivo y cargarlo en un PictureBox?
El código es muy simple pero suele generar problemas.
[C#]
private void btnBuscarImagen_Click(object sender, EventArgs e) { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = "Archivo JPG|*.jpg"; if (fileDialog.ShowDialog() == DialogResult.OK) { picImagenEmpleado.Image = Image.FromFile(fileDialog.FileName); } }
[VB.NET]
Private Sub btnBuscarImagen_Click(ByVal sender As Object, ByVal e As EventArgs) Dim fileDialog As New OpenFileDialog() fileDialog.Filter = "Archivo JPG|*.jpg" If fileDialog.ShowDialog() = DialogResult.OK Then picImagenEmpleado.Image = Image.FromFile(fileDialog.FileName) End If End Sub
Persistir la edición
La operación de persistir los datos o guardarlos requiere dos etapas, una implica tomar la información de los controles y generar los objetos de dominio que la capa de datos requiere para llevar a cabo la actualización en la base de datos, la segunda será simplemente procesar la entidad generando los INSERT y UPDATE necesario.
[C#]
private void btnGuardar_Click(object sender, EventArgs e) { // // Se crea la entidad // EmpleadoEntity empleado = new EmpleadoEntity() { IdEmpleado = _idEmpleado.GetValueOrDefault(), Nombre = txtNombre.Text, Apellido= txtApellido.Text, FechaNacimiento = dtpFechaNacimiento.Value, EstadoCivil = Convert.ToInt16(cbEstadoCivil.SelectedValue), Imagen = ImageHelper.ImageToByteArray(picImagenEmpleado.Image) }; // // Se asignan los estudios seleccionados, se unicializa la lista // para cargar la selecciond el usuario // empleado.Estudios = new List<EstudioEntity>(); IEnumerable<DataGridViewRow> rowsSelected = dgvEstudios.Rows.Cast<DataGridViewRow>() .Where(o => Convert.ToBoolean(o.Cells["Seleccion"].Value)); foreach (DataGridViewRow row in rowsSelected) { EstudioEntity estudio = new EstudioEntity() { IdEstudio = Convert.ToInt32(row.Cells["IdEstudio"].Value) }; empleado.Estudios.Add(estudio); } // // se graba // EmpleadosDAL.Save(empleado); this.DialogResult = DialogResult.OK; this.Close(); }
[VB.NET]
Private Sub btnGuardar_Click(sender As Object, e As EventArgs) ' ' Se crea la entidad ' Dim empleado As New EmpleadoEntity() With { _ .IdEmpleado = _idEmpleado.GetValueOrDefault(), _ .Nombre = txtNombre.Text, _ .Apellido = txtApellido.Text, _ .FechaNacimiento = dtpFechaNacimiento.Value, _ .EstadoCivil = Convert.ToInt16(cbEstadoCivil.SelectedValue), _ .Imagen = ImageHelper.ImageToByteArray(picImagenEmpleado.Image) _ } ' ' Se asignan los estudios seleccionados, se unicializa la lista ' para cargar la selecciond el usuario ' empleado.Estudios = New List(Of EstudioEntity)() Dim rowsSelected As IEnumerable(Of DataGridViewRow) = dgvEstudios.Rows.Cast(Of DataGridViewRow)().Where(Function(o) Convert.ToBoolean(o.Cells("Seleccion").Value)) For Each row As DataGridViewRow In rowsSelected Dim estudio As New EstudioEntity() With { _ .IdEstudio = Convert.ToInt32(row.Cells("IdEstudio").Value) _ } empleado.Estudios.Add(estudio) Next ' ' se graba ' EmpleadosDAL.Save(empleado) Me.DialogResult = DialogResult.OK Me.Close() End Sub
Es preciso remarcar como en la entidad “Empleado” es cargada la lista de Estudios que este posee y solo una entidad es enviada desde la Presentación a la capa de datos. Durante esta operación también se toma la imagen del PictureBox y se convierte en un array de byte.
La actualización realiza varias operaciones las cuales son muy extensas en código, por lo tanto no será puesta directa en el articulo, pero si podrán verse en el código de ejemplo que puede descargarse.
Código de Ejemplo
La base de datos utilizada en el ejemplo es la Sql Server Express 2008 R2, como ver en la solución el mdf esta integrado al Visual Studio, por lo tanto con solo tener el sql server express instado esta debería funciona adjuntándose sola al servicio.
En la carpeta “script” del proyecto “DataAccess” se encuentra un archivo .sql con las instrucciones para crear la estructura de tablas y datos que se requieren para este articulo.
[C#] |
[VB.NET] |
hola leandro soy nuevo en tu blog, me llamo luis soy del hermano país de Perú, tenia un par de consultitas, la primera es concerniente a los escenarios desconectados y conectados, veo que tu utilizas escenarios conectados en tus ejemplos, segun la msdn recomiendan usar modo conectado, me podrias explicar un poco mas al respecto pero basado en tu experiencia..., la segunda duda es que veo que vos utilizas metodos estaticos, o shared, la verdad yo no estaba acostumbrado a usar metodos estaticos, me podrias explicar un poco alas ventajas y desventas de usar metodos estaticos y shared contra la forma tradicional en cuanto a rendimiento performance, etc.. muchas grcias espero puedas aclarar mis dudas y mucho exitos ...
ResponderEliminarperdon quise decir que la msdn recomienda usar escenarios desconectados, me confudí....
ResponderEliminarhola luis fernando
ResponderEliminarEn realidad estos ejemplos son todos escenarios desconectados, si analizas bien veras que se usa el reader solo lo suficiente para cargar al entidad, pero solo eso, despues se continua con la entidad en memoria ya cargada, el reader se desconecto una vez terminada esta operacion.
Por lo tanto este tambien es un escenario desconectado, lo que pasa es que seguro asocies al reader con conectado y al dataset con no conectado, pero en realidad esto se refiere a que el reader permenece vivo durante toda la transaccion, en cambio aqui no solo el tiempo justo para cargar una entidad.
El tema de los metodo estaticos se debe a que tanto al capa de negocio, como al persistencia, implementan funcionalidad al estilo de proceso, no aplican conceptos de herencia o sobrecarga de operadores ni nada de lo orientado a objetos, solo procesan las entidades. Recuerda que donde se usa static (shared) son los metodo de las capas y solo alli.
La capa de negocio seria se denomina tambien capa de Servicio, y esta implementa el patron Facade, por lo tanto al ser la entrada al sistema el usarlo static (shared) reduce el tener que crear la instancia por cada clase usada, ademas seria muy raro que apliques logica de POO sobre estos metodos.
saludos
hola muchas gracias leandro, me aclaraste mi duda, teremendamente, ahor te voy a ser otra pregunta, espero no incomodar, siempre en aplciaciones para windows y en aplicaciones web en mi experiencia, grababamos las imagenes, archivos o imagenes , solamente su ruta, mas no lo grababamos como tipo de datos image, usabamos varchar(255), ahora cuales son las ventajas de grabar el binario o la ruta, en temas de rendimiento, performance, bye y ojala y exitos...
ResponderEliminarHola leandro, gracias por responderme, muchas gracias, te quiero hacer una nueva pregunta, siempre veo en tus ejemplos ue usas sentencias SQL embebidas y parametrizadas, no crees ue es mejor usar Stored Procedure, o lo haces asi por son post de ejemplos y para un proyecto real definitavemente se tendria ue usar SP, cual es tu opinion concerniente a los Stored Procedure, VENTAJAS, desvntajas, tu los sueles usar en tus proeyctos reales, muchas gracias y exitos..
ResponderEliminarHola Leandro. Una vez más gracias por la información publicada. Me gustaría que me dieras una sugerencia, estoy conectada a un servidor por ssh y se demora un poco subiendo cada imagen. Te echo el cuento, el sistema hace 4 procesos,escanea (1 o varias imagenes), realiza unos calculo, imprime y guarda, la cosa es que si hago el proceso secuencial el usuario espera mucho por cada imagen. Ahorita, estoy escaneando, luego los cálculos, guardo una info, luego imprimo y simultáneamente guardo la imagen asociado a los datos que guarde previamente, el problema es que cuando son muchas imágenes me quedan registros sin las mismas, a veces completa la impresión y a veces no. Alguna idea? Como hago para trabajar con varias conexiones a la vez? Gracias!
ResponderEliminarhola Pierina Joplin
ResponderEliminarSi es un tema de conectividad lo primero que se podria evaluar es de mejorarla, o sea si esto es una tarea critica para el trabajo operativo se pdoria pedir que la conexion seguro aumente el ancho de tranferencia, porque sino entendi mal esta conexion seguro tiene poca tasa de tranferencia.
Otra tecnica podria que ser realicer tareas en batch de forma desatendida, o seas separa las tareas, que necesitas hacer en el momento, y deja otras para que se registren pero se completen mas tarde, por ejemplo si el tema de la tranferencia es critico, podrias dejar encoladas los registros en una db, y que un proceso posterior, quizas nocturno, realice las transferencias por el canal seguro, pero el registro lo haces local en una db, y el proceso nocturno podrias ser un Servicio de Windows que se ejecute solo a cierta hora
saludos
hola lyc1903
ResponderEliminarsiempre en aplciaciones para windows y en aplicaciones web en mi experiencia, grababamos las imagenes, archivos o imagenes , solamente su ruta, mas no lo grababamos como tipo de datos image..
en realidad la decision depende mas que nada de que tan critica es la imagen, si se trata de la foto de un empleado, por ahi una tecnica u otra podria ser indistinta.
Pero que sucede si la imagen es un contrato legal, o el plano de alguna pieza de produccion, ahi la cosa cambia porque la imagen es un dato critico para la entidad, alli es cuando dejar la imagen suelta en un directorio puedo no ser una opcion y se registra esta directo en un campo de la db.
En Sql Server 2008 se introduce una opcion que podria ser util, el FILESTREAM
saludos
HOla una pregunta, estoy validando un datagridview mi problema es el siguiente, cuando doy clic en agregar (productosBindingSource.AddNew()
ResponderEliminarme agrega la fila, pero digamos que en el caso que seleccione otra fila que tengo solo como lectura, se me cierra la que se agrego!!! Gracias Saludos...
hola Edgard Geovanny
ResponderEliminarEsta algo generico el planteo de la pregunta como para dar una respuesta de que puede estar pasando.
Entiendo que si has puesto AddNew, has activado la accion para dar de alta un nuevo registro, el salir de este sin haber aplciado el Update() del registro para persistirlo en la tabla imagino hace que esta accion se cancele.
Igual no estoy del todo seguro, puede que esta sea la accion predeterminada al dar de alta un registro, o sea si quitas el foco del registro la accion se cancela.
Por ahi deberias hacer el planteo en el foro de MSDN
Foro VB.NET
Alli podrias plantear la pregunta con mas detalle, quizas la siga respondiendo yo, o sino alguien mas podria dar una mano.
saludos
Hola, esto funciona cuando almacena en un campo image; pero cuando almacenas el path de donde esta la imagen cual seria el procedimiento para cargar la imagen en el CR si realizas el select y lo almacenas en un archivo *.html y de ahi le llamas a CR me explico? quiza sea claro.
ResponderEliminarhola JOSÉ ANTONIO
ResponderEliminarLo que no me quedo claro es el tema de html, no sera quizas aspx a lo que hacias referencia?
Mas alla que sea un proyecto web o winforms lo que vas a necesitar hacer es agregar a ese datatable un campo del tipo byte array y cargar la imagen alli usando de base el nombre de la imagen
Seguramente debas, despues de hacer la consulta a la tabla, recorrer los registros del datatable, del dataset tipado, y buscar cada imagen para colocarla en ese campo byte[]
para esto usarias el metodo:
File.ReadAllByte
Por cada row del datatable armas la ruta al archivo, recuperas el byte array del mismo y los cargas, para al final tener las imagenes y enviarlas al reporte.
saludos
Hola leandro, muchas gracias por el codigo que pones a disposicion, te comento que me surge un Qeubrantamiento de Cabeza, ahora te contare mi problema, no tengo mucha experiencia en base de datos ni en Modelamiento, asi es que espero no te aburran mis pregunta novatas.
ResponderEliminarmi duda es con respecto a la relacion de las tablas EMPLEADO Y EmpleadosEstudios, TENGO ENTENDIDO QUE LA TABLA: "EmpleadosEstudios" ES UNA TABLA DETALLE, HASTA AHI BIEN, PERO AHORA COMO REGISTRAR DESDE MEDIANTE UN INSERT INTO UN REGISTRO DE EMPLEADO CON SU PRIMARIA, SECUNDARIA, Y UNIVERSIDAD, ESD DECIR ESTE EMPLEADO TIENE ESOS 3 NIVELES DE ESTUDIO A LA VEZ, ESA ES MI DUDA COMO REGISTRAR LA TABLA DETALLE, PODRIAS AUYDARME DANDOME EL QUERY DE COMO INSERTAR UN EMPLEADO CON ESOS ESTUDIOS??, POR FAVOR, YA LLEVO UN PAR DE DIAS CON ESTE PROBLEMA...
GRACIAS POR TU TIEMPO...!!
hola Johnny
ResponderEliminarPrimeramente un punto para corregir, la tabla "EmpleadosEstudios", no es una tabla de detalle, es una tabla que permite definir una relacion mucho a mucho
Esto tinee que ver con el Modelo entidad-relación
Bien aclarado ese punto, para insertar en la tabla es simple solo creas una query del tipo
INSERT INTO EmpleadosEstudios (IdEmpleado, IdEstudio) VALUES (@isempleado, @idestudio)
con esa simple consulta ahora lo que haces es pasar los parametros
El empleado sera siempre fijo, este no varia porque es el que editas y los estudios los insertas en un loop uno por uno, o sea si tienes 3 estudio para ese empleado ejecutaras este mismo INSERT 3 veces, uno por cada id de estudio que tengas
Igualmente una aclaracion, esto es si el empleado se registrs la primera vez porque no tendra ningun estudio asignado, pero que sucede si es una modificacion y de 3 ahora solo le marcas 1 estudio
Bien en ese caso lo que simpre ahacer priemro es un DELETE
DELECT From EmpleadosEstudios WHERE IdEmpleado = @idEmpleado
Este delete lo haces siempre y luego vuelcas la info del los estudio, de esta forma evitas hacer un marge completo de los datos existentwes con la nuevas modificaciones
O sea harias siempre asignaciones con el insert
bueno, espero hay quedado claro
saludos
Hola,se que esto puede sonar algo tonto :S , pero aparte de esta manera:
ResponderEliminarDim rowsSelected As IEnumerable(Of DataGridViewRow) = dgvEstudios.Rows.Cast(Of DataGridViewRow)().Where(Function(o) Convert.ToBoolean(o.Cells("Seleccion").Value))
No hay alguna otra manera de recuperar los estudios seleccionados en el grid?? Lo pregunto porque aquí veo algunas cosas que me resultan completamente nuevas :( y no se si también me podrías indicar que conceptos has aplicado??. Saludos y Gracias ;)
hola Alexandra
ResponderEliminarComo haber siempre hay otras formas de hacer algo
pero si en este caso se dipone de .net 3.5 porque no aprovechar todas su potencia usando una expresion lambda para filtrar la seleccion
Lambda Expressions (Visual Basic)
La alternativa a esa linea de codigo serian muchas linea para implementar un foreach por cada row evaluando cuales estan marcadas y pasandolas a una lista auxilia,
pero es una linea como impliquemente aqui contra por lo menos 4 o mas del for.
saludos
Hola una consulta, a que se debe que cuando intento registrar un nuevo empleado o editar uno existente obtengo este error :"MSDTC NO esta disponible en el servidor"??
ResponderEliminarGracias de antemano :D
hola Edalo
ResponderEliminarMSDTC NO esta disponible en el servidor
Ese error tiene que bver con el uso de transacciones, hay un servicio que requiere estar habilitado para que funcione, prueba con el comentario del link siguiendo los pasos a ver que sucede
saludos
Estimado Leandro como siempre muy buenos tus post, queria consultarte algo que para mi es nuevo, almomento de declarar la variable del codigo del empleado lo haces asi.
ResponderEliminarint? _idEmpleado
Para que es el signo de interrogacion?
Luego usas el
_idEmpleado.HasValue y el _idEmpleado.GetValueOrDefault().
no se si puedes por favor explicar que hace esto???
Saludos
hola Fernando
ResponderEliminarel ? despues de un tipo de dato lo define como nulable
o sea puede asignar un null a esa variable, cuando no sabes que dato tendra
Tipos que aceptan valores NULL (Guía de programación de C#)
saludos
Hola Leandro, estoy comenzando a programar con C# y me está costando un poco el tema de las listas. Para lo cual bajé tu código donde declaras la clase EmpleadoEntity, pero me da el siguiente error al compilar:
ResponderEliminar"DataAccess.Entidades.EmpleadoEntity.IdEmpleado.get' debe declarar un cuerpo porque no está marcada como abstract o extern"
¿esto puede ser porque estoy usando Visual Studio 2005?
Desde ya agradezco tu predisposición y tu tiempo.
PD1: No encontré que postearas sobre listas, pero si tienes algo (a parte de MSDN) te agradezco.
PD2: Estoy renegando con listas porque tengo una pantalla con muchas combinaciones posibles de filtro y una lista es la única forma que se me ocurre para pasar los parámetros y sus valores opcionalmente. Ya que los arrays son de dimensión fija.
hola Andrés
ResponderEliminarel tema con el error es que el ejemplo que has descargado esta desarrollado con VS2008 y .net 3.5
por lo tanto la definicion de las propiedades que ves alli tienes la variable auto implementada
si usas VS2005, o sea .net 2.0 debes declarar al variable privada que usar la propiedad
private string nombre;
public string Nombre
{
get { return nombre; }
set { nombre= value; }
}
como veras en tu caso asi es como debes declarar todas las propiedades, porque la forma que yo lo uso es algo particular de .net 3.5
con respecto a las listas, no has evaluado usar listas genericas
Clase genérica List
saludos
Gracias Leandro!
ResponderEliminarSos grosso.
Saludos desde Venezuela! no ha pensado en hacer un VIDEO TUTORIAL de esta entrada?
ResponderEliminarhola Rafa
ResponderEliminarla verdad no me lo habia planteado, igual este tema en particular apunta a mostrar un ejemplo implementado, no es que explica alguna caracteristica de programacion concreta, es muy general el tema para un video
saludos
Hola nuevamente Leandro, cómo estás?
ResponderEliminarTe comento que estoy trabajando con listas en C#, pero me surge una duda cuando tengo que grabar en BD esta información.
Por ahora lo hago de la siguiente forma, pero que hay una forma más eficiente con un RecordSet.
foreach (Parametro prime in Lista.Parametros)
{
SqlCommand Comando = new SqlCommand(prime.campo, cnn);
Comando.CommandType = CommandType.StoredProcedure;
if (prime.campo == "Insertar")
Comando.Parameters.AddWithValue("@Descripcion", prime.valor);
Comando.ExecuteNonQuery();
}
Me parece que no está bueno crear un comando por cada elemento de la lista. ¿a vos qué te parece?
Gracias de antemano!
Ya que estamos, voy con otra duda que tengo con un DataGridView. Porque necesito poder seleccionar las filas y columnas completas.
ResponderEliminarCon la propiedad "SelectionMode = RowHeaderSelect" puedo seleccionar solo las filas en ejecución y con "RowHeaderSelect" puedo seleccionar solo las columnas, pero no tengo un valor para ambos.
También probé con código como el siguiente para las filas y funciona..
grid.CurrentRow.Selected = true;
Pero para las columnas no encuentro la forma. Probé con..
gridPrecios.Columns[gridPrecios.CurrentCell.ColumnIndex].Selected = true;
Pero no le encuentro la vuelta al asunto todavia.
Aclaro que no pretendo seleccionar las filas y columnas completas a la misma vez (lo que sería toda la grilla). Necesito poder seleccionar toda una fila o toda una columna en tiempo de ejecución. Porque también estoy usando la grilla para editar los valores de las celdas por otro lado.
Espero que se entienda la pregunta.
Gracias de nuevo!
hola Andres
ResponderEliminarpodria ahcer algo como esto
SqlCommand Comando = new SqlCommand(prime.campo, cnn);
Comando.CommandType = CommandType.StoredProcedure;
foreach (Parametro prime in Lista.Parametros)
{
Comando.Parameters.Clear();
if (prime.campo == "Insertar")
Comando.Parameters.AddWithValue("@Descripcion", prime.valor);
Comando.ExecuteNonQuery();
}
hola Andres
ResponderEliminarbien la verdad con respecto al SelectionMode del DataGridView, no creo que puedas implementar esta funcionalidad
entiendo lo que quieres hacer, pero lavd con este control nucna he visto que se pueda.
igualmente me parece algo raro este tipo de seleccion porque lo normal es resaltarle al usuario aquella columna o fila que le interece como dato
despues dedee codigo ya no afecta porque puede tomar el CurrentRow, o CurrentCell y con este ultimo por ejemplo sabes la fila con el RowIndex, y la columna con el ColumnIndex
con lo cual con la info puede operar sin problemas, mas alla del resaltado visual
saludos
gracias muuy bueno el ejemplo!!!!
ResponderEliminarhola leandro muuy buen blog
ResponderEliminartengo una duda se puede aplicar todo esto para una base de datos en access 2003??
la duda es por que veo que utilizas transactionScope y esta funcion no se aplica para access.. entonces la duda es:
cual metodo(si lo hay) es parecido al transaction scope que se pueda aplicar en access??
Hola Ruben
ResponderEliminarCon respecto a la edicion del empleado se podria implememntar sin problemas en Access, solo que ingresar la imagen dentro de la db no seria muy recomendable, porque access puede degradar la performance.
Las transacciones es obvio que TransactionScope no aplica, vas a necesitar usar el OleDbTransaction
entonces iniciar y cerrar la trasnaccion, la macana con esto es que ya deja de ser transparente cuando programas en capas, porque debes pasar la conexion en cada invocacion si la logica pega en varias entidades.
saludos
hola de nuevo Leandreo muy util tu ejemplo pero tengo una duda
ResponderEliminarsi yo heredo la plantilla de un formulario (es la que utilizo)
cuando hagoi clic en mi grilla este abre supuesta mente el formulario pero este formulario aparece en blanco, es decir no carga ninguno de los controles que le coloque(los textbox) por que sucede eso?
Hola Leandro soy nuevo por aquí exelente tu blog, estoy desarrollando una aplicación parecida, mi consulta es que al traer los datos en una grilla de una tabla en particular quiero mostrar la descripción de los id asignados, es decir por ejemplo tengo una tabla hospitales hago un reader de la misma que tiene un id_provincia y id_region que hacen referencia a sus respectivas tablas y quiero que muestre la descripción de la provincia y región.
ResponderEliminarSi bien al crear la consulta en la capa "AccesoDatos" utilizo un inner join para combinar las tablas pero al llamar al método y mostrarlo en la grilla no me muestra los datos de esos campos.
Desde ya gracias...
hola Ruben
ResponderEliminarpuede suceder por varias cosas, pero una que se me ocurre es que valides el codigo del Designer.cs asociado al formulario, alli deberia estar el codigo que diseña el form con la ubicacion de cada control que lo conforma
tambien podrias probar de crear un for nuevo y validar si sucede lo mismo
valida ademas que la aplicacion compila sin errores
saludos
hola Augusto
ResponderEliminarla capa de accso a dato con que tipo de entidades trabaja ?
porque si lo haces con dataset tipados puede que la query devuelva los 4 campos, o sea los 2 ids y las 2 descripciones
pero si solo sabe mapear dos porque son solo las dos columans del id que tiene definidas las otras las descarta
o sea deberia actualizar el modelo o crear una entidad nueva que tenga estos 4 campos paera que la query con el join devuelva los datos pero la entidad tiene wue saber mapearse
si usas clases creadas por ti deberias en el while del reader asignar las propiedades al objeto, asi como ahra los haces con las dos propiedades ids, debes agregar las de las descripciones
saludos
Hola Leandro
ResponderEliminarE modificado la entidad con la que trabajo en la capa datos agregándole las descripciones y ahora me funciona como esperaba muchas gracias por la ayuda.
Que tal Leandro, estoy utilizando vb2005, como grabo la imagen en la bd?, no existe la propiedad imagehelpe.imageToByteArray(imagen), al tratar de introducir el parametro me sale el error "Error al convertir el valor de bitmap a byte()"; te cuento que utilizo la siguiente sintaxis: cmd.Parameters.add(new sqlparameters("@foto").sqlType.VarBinary)
ResponderEliminarcmd.parameters("@foto").value = me.pixturebox1.image; si me podrias dar una mano.
hola jorge
ResponderEliminarEl tema es que no puede hacer esto
cmd.parameters("@foto").value = me.pixturebox1.image
porque no es valido, elpetro espera un array de byte, y tu no se lo estas dando por eso falla
si analiza el codigo del ejemplo del articulo, veras una clase de nombre ImageHelper
esta es la que contiene las funciones de conversion de Image a un array de byte que requieres para asignar el parametro
saludos
Correcto Leandro lo revise y solucione el tema, gracias. Te sigo!!
ResponderEliminarhola gracias por tu respuesta Leandro pero tengo una consulta mas sobre esto
ResponderEliminarhe seguido el ejemplo del link y todo funciona bien excepto que tengo un problema he aplicado el mismo codigo en otra grilla (claro que para esta aplico un objeto diferente, una clase diferente) y no me llena la grilla cuando corro el programa, ademas como me explicaste he aplicado la propiedad DataPropertyName para cada columa (este valo es el mismo que aplico en las propiedades del objeto)
lo que me extraña que tenga varias grillas y algunas las llena y otras no, el problema no son los querys ya que los he probado y todos me devuelven los valores que quiero ademas no creo que sea la clase o el llamada a esta porque esta es una rutina y como te menciono en algunas grillas devuelve el valor y en otras no?
ademas he comprobado los DataPropertyName de las grillas y si coinciden con los propiedades del objeto que quiero recuperar que crees que puede ser el error?
hola Ruben
ResponderEliminarla verdad bastante raro el problema que describes, porque que en algunas grid funcione y en otras no, no tendria mucha logica, o sea funciona o no funciona si es que en todas aplcias la misma tecnica para cargar la imagen
has validado que la propiedad AutoGenerateColumns lo pongas en false
prueba de asignar a las tablas con problemas los datos d las grid que cargan correctamente, para validar si es algo de datos el tema
saludos
amigo nesecito su ayuda para mostrar una serie de imagenes que tengo en la base de datos pero en vez de un datagriview es un listview quiero mostrar las imagenes en formato de vista previa
ResponderEliminarhola Ali
ResponderEliminarel tema es que si es un listview deberias agregar estas imagenes en un ImageList para luego vincular con el listview
http://social.msdn.microsoft.com/Forums/es/vbes/thread/aadfe755-680f-4870-ad91-d60ddda2e56b
puedes agregar imagenes en timepo de ejecucion recuperando estas desde la db
saludos
Hola Leandro tengo un problemita al querer visualizar la imagen por default en un picturebox cuando quiero hacer una nueva entrada de un registro me da este error "Value of 'null' is not valid for 'stream'." previamente llamo en en load del form al método para que cargue la imagen por default al control creo que no encuentra la ruta de acceso si no me equivoco no se si sera por algún error de referencia o algo que me este faltando desde ya gracias.
ResponderEliminarhola Augusto
ResponderEliminarme suena mas a un problema de la logica de codigo que aplicas
sera que la imagen que recuperas esta en null ?
pueden ser miles los problema que geenren este error, la unica forma de solucionarlo es poniendo un breakpoint y validando que valores toma la asignacion que haces el picturebox
saludos
Hola Leandro te agradezco por tu códigos me han servido mucho exitos y bendiciones en tu vida
ResponderEliminaruna pregunta como puedo convertir esto
ResponderEliminarrowDatosCliente.DNI = pictureBox1.Image
ya que al intentar cargar de un picturebox.Image meda un error de tipo Byte[]
he intentado con system.byte[picturebox.image] y con convert.______ y no e podido. para mi seria un honor que me puedas ayudar. gracias
hola luis
ResponderEliminarpero no veo mucha compatibilidad entre esos campos, un DNI que sea una imagen es algo raro, el dni no es un campo numerico ?
como vas a poner una imagen alli
ademas si revisas el ejemplo veras que hay un clase helper que permite convertir el Image en byte[], deberias usarla
saludos
es que es rowDatosCliente.foto = pictureBox1.Image
ResponderEliminares para cargar la foto en se encuentra cargada en el picturebox
es que este metodo me funciona mejor
ResponderEliminardtCompra.DatosClienteRow rowDatosCliente = facturacion.DatosCliente.NewDatosClienteRow();
rowDatosCliente.Nombre=Convert.ToString*txtNombre.Text);
rowDatosCliente.cantidad =Convert.toint32(txtcantidad.Text);
rowDatosCliente.precio=Convert.toint32(txtprecio.Text);
rowDatosCliente.total=Convert.toint32(txttotal.Text);
rowDatosCliente.codigo_barra=pictureBox1.Image;
la imagen es un codigo de barra que se genera automaticamente.
el error: es(
No se puede convertir implicitamente el tipo 'System.Drawing.Image'en'byte[]')
hola luis
ResponderEliminarbien, pero el Image de un Picturebox no es compatible con un campo de la db, deberias convertir este a un byte array
si analizas el articulo veras que hay una clase helper para esto, lo has evaluado?
saludos
Saludos leandro
ResponderEliminares que estoy cargando directo del formulario al crystal report. pero para guardarlas la cargue en un memorystream llamado ms esto sera lo que boy a convertir. puedo enviarle el proyecto para que lo vea.
Saludos leandro
ResponderEliminarya resolvi el problema te lo muestro
por si alguien tiene el mismo problema aki esta la solucion
System.IO.MemoryStream ms = new System.IO.MemoryStream();
pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
PurificadoraDataSet facturacion = new PurificadoraDataSet();
PurificadoraDataSet.VentasRow rowventas = facturacion.Ventas.NewVentasRow();
rowventas.cliente = Convert.ToString(txtcliente.Text);
rowventas.cantidad = Convert.ToInt32(txtcantidad.Text);
rowventas.precio = Convert.ToInt32(txtprecio.Text);
rowventas.total = Convert.ToInt32(txttotal.Text);
rowventas.ncf = Convert.ToString(txtncf.Text);
rowventas.fecha = Convert.ToString(txtfecha.Text);
rowventas.idfactura = Convert.ToInt32(txtidfactura.Text);
--- rowventas.codigo_barra = ms.ToArray();-----
mil gracias por tus aportes.
Hola Leandro.
ResponderEliminarEstoy desarrollando una aplicación en la que quiero mostrar varias imagenes pequeñas de diferentes tamaños para elegir una. Alturas entre 40 y 100px, anchuras entre 100 y 500px. La cantidad de imagenes a mostrar será entre 5 y 20 imagenes.
Actualmente no usa base de datos pero en un futuro si tendrá esta opción.
¿Que control me recomiendas para mostrar las imagenes?
Había pensado usar PictureBox generados dinámicamente, pero es posible que un listview o un DataGridView u otro sea mas recomendable.
Saludos, enhorabuena por tu gran trabajo y gracias por la información.
hola David
ResponderEliminaro sea apuntas a algo como esto
Image Thumbnail Viewer with .NET 2.0
el tema que control estandar desde .net para este tipo de trabajo con imagenes no hay, salvo el ImageList pero no es para temas visuales sino para referenciar imagenes por medio de uan key en una coleccion
saludos
hola leandro, te molesto,,, por mas que intento, en la parte de codigo donde pones:
ResponderEliminargrilla.AutoGenerateColumns=false;
no consigo que entre al bucle debajo para recorrer la grilla sacarle el objeto, verificar su campo imagen y convertirla de arreglo de bytes a imagen para luego mostrarla en dicha grilla. Seteaste algo en la grilla en diseño o hay algun code que no estoy viendo bien?
David
hola David
ResponderEliminarpero asignas el DataSource ? y puedes verificar que se generen registros ?
o sea descarta el realizar el foreach por cada row y solo deja que los datos se muestren en el grid, puede ver filas? sino las visualizas alli esta el problema no hay info cargada por lo tanto tampoco se podra recorrer nada
valida como recuperas los datos desde la db
saludos
Todo bien Leandro, mi error en:
ResponderEliminargrilla.AutoGenerateColumns=false;
era que cuando armo los encabezados de la grilla manualmente, no estaba seteando la propiedad:
DataPropertyName=CampoClase
Ahora funciona bien, pero, el unico error raro, salto con algo relacionado con el evento DataError de la grilla y se me borran todas las columnas de la misma. Estoy tratando de volver a generar el error asi doy detalles pero parece que desaparecio. Ja
Saludos
Leandro gracis por tu ayuda con esto, me podrias ayudar estoy haciendo un reporte en donde deben de salir 22 fotos que son los alumnos por cada aula, tendria que hacerlo colocando solo el path y que llame a la foto o como?
ResponderEliminardesde ya gracias
hola Orlando
ResponderEliminarpor reporte, te refieres a que usas crystal ? o sea seria algo como esto
Crystal Reports – Cargar imagen usando una capa de reporte
quizas en tu caso debas primero recorrer el datatable y recuperar als ruta de las imageens para poder asignar a un campo extra que definas en el datatable tipado el byte[] de la imagen que vas a visualizar
saludos
Hola Leandro.Soy Sandra
ResponderEliminarEsta publicacion me ha aclarado muchas dudas sobre un proyecto que estoy realizando, sin embargo tengo una problema con el cual me gustaria que me ayudaras.
Tengo que hacer un formulario de captura para productos, clientes, entre otros. Pero el problema está en el sistema tiene que crear automaticamente un codigo ya sea de producto, de cliente, etc, igualmente tengo que crear consultas parametrizadas de la forma: desde hasta, tanto con fechas como por direccion o nombre de articulo o por precio, etc.
Por ejemplo: desde la a hasta la d
Sou novata en esto y ahora estoy comenzando a aprender por lo que te agradeceria en el alma que me ayudaras con esto.
hola Sandra
ResponderEliminarcon respecto al codigo del producto, imagino tienes un campo key que defines como identity en la tabla, no ? porque no puede ser ese el codigo
o apuntas a un codigo diferentes algo alfanumerico? si es asi que este camo no se la key de la tabla que sea un campo adicional
para las busquedas podrias aplicar este concepto
Filtros Condicionales (1/2)
como veras se filtra con una variedad de opciones
saludos
Gracias por el ejemplo de las búsquedas, es justamente lo que quería, pero sin embargo me sigue la duda respecto al código de registro, porque el problema es que definiendo el campo tipo identity como apuntas, el id que se genera es de tipo 1, 2, 3, etc. según el orden de los registros y yo los necesito que sean por ejemplo: 000001, 0002 o AS0005, AS002.
ResponderEliminarAdemás lo que pasa es que aún no conozco la forma de que este código se cree de forma automático en sql y no que el usuario tenga que insertarlo en el momento en que se agrega el registro.
Espero que entiendas mi pregunta porque creo que no me sé explicar bien.
Muchas gracias, espero que me puedas ayudar.
hola Sandra
ResponderEliminarsi la idea es usar 00001 eso es solo formato, podrias dejar que se cree secuancial con el identity y luego usas
string id = string.Format("{0:0000}", 2);
con eso obtienes un 0002, pero lo resuleves cuando lo muestras nada mas, en la db solo ser un 2
ahora si es S002 la cosa es otra, recomendaria que alli tendras una clave compues de dos campo unao para la letra " y otro para el numero, no uses un solo campo, podrias suar el Max() para tomar el ultimo id he incrementar
SELECT Max(id) FROM Tabla WHERE codigo = 'S'
por supuesto la forma en que cambias de codigo eso el negocio imagino lo define
saludos
Buenas leandro muy buen blog primeramente te felicito porque me ha ayudado mucho.
ResponderEliminarBueno mi problema es el siguiente: tengo un form con un data grid view y un picture box. quiero que al seleccionar una fila dentro del datagridview me muestre la foto en el picture box. mi programa es de un almacen y quiero colocar fotos, me gustaria saber la manera mas sencilla de hacerlo. trabajo en vb.net y access 2007.
espero su respuesta
hola Leandro muy bueno todas tus publicaciones ,queria pedirte un fabor si podrias ayudarme en una coneccion :
ResponderEliminartengo un procedimiento almacenado REGISTRAR:
ALTER PROCEDURE [dbo].[registrar]
@tipocuenta int,
@nom_usu varchar(50),
@pass varchar(50),
@pregunta varchar(50),
@respuesta varchar (50),
@email varchar(50)
AS
BEGIN
if exists(select * from cuenta where cuenta.nombre_usuario=@nom_usu)
begin
raiserror('Nombre de usuario ya se encuentra registrado',11,1)
end
else
begin
insert into cuenta (nombre_usuario,contraseña,id_tipo,pregunta,respuesta,email)values(@nom_usu,@pass,@tipocuenta,@pregunta,@respuesta,@email)
end
END
cual seria el codigo para que me muestre el raiserror en VB y C# en un label con el nombre "lblerror" o si podrias hacer un proyecto con eso,le agradeceria mucho su ayuda
hola Leonel
ResponderEliminarpero las fotos dondes estas ubicadas, dentro de la db, o en una carpeta ?
porque si es en una carpeta podrias tomar el nombre del archivo y usar
Picturebox1.Image = Image.FromFile(ruta)
para mostrar la imagen
saludos
hola JHON
ResponderEliminarpodrias usar el try..catch y capturar el SqlException
http://social.msdn.microsoft.com/Forums/es/vcses/thread/99982a71-627c-4fe3-870d-84a4c61739b3
http://social.msdn.microsoft.com/Forums/es/vbes/thread/e36ae5e9-7b43-41d8-aeed-8dc877365cfe
saludos
Hola de Nuevo Leandro, con respeto a lo de las imágenes yo también tengo una pregunta.
ResponderEliminarComo podría hacer para guardar una imagen en una carpeta, o sea, en el momento que inserto X registro a la base de datos buscar una imagen en el computador, asignarle un nombre relacionado con el registro que estoy creando y guardarla en otra carpeta especifica, esto seria para no sobrecargar la BD con imágenes.
Eso es lo primero
lo segundo es que estoy realizando un formulario de consulta con el siguiente código:
private void comando()
{
conexion = new SqlConnection(cc);
conexion.Open();
cmd = new SqlCommand(consulta, conexion);
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
MessageBox.Show("Registro encontrado");
reader.Close();
SqlDataAdapter adap = new SqlDataAdapter(consulta, conexion);
DataTable dtProductos = new DataTable();
adap.Fill(dtProductos);
this.dgvProductos.DataMember = "dtProductos";
this.dgvProductos.DataSource = dtProductos;
button1.Enabled=false;
textBox1.ReadOnly = true;
btnNuevaConsulta.Enabled = true;
}
else
{
MessageBox.Show("REGISTRO NO ENCONTRADO");
reader.Close();
}
conexion.Close();
}
private void button1_Click(object sender, EventArgs e)
{
//conexion = new SqlConnection(cc);
try
{
if (cbCriterio.Text == "Codigo Porducto")
{
if (textBox1.Text.Length == 0)
{
MessageBox.Show("El textBox esta vacio");
}
else {
consulta=(" SELECT * FROM productos WHERE IdProducto = '" + textBox1.Text + "'");
comando();
}
Cuando lo ejecuto y realizo una primera consulta todo funciona perfecto, pero luego cuando quiero realizar otra sin tener que ejecutar el formulario me da el siguiente erro: "child list for field dtproductos cannot be created".
Esto ha sido un verdadero problema y por mas que lo intento no encuentro en donde esta error.
Te agradecería mucho como siempre que me ayudaras.
Gracias Por Anticipado
gracias Leandro por la atencion inmediata ,funcionó:
ResponderEliminarALTER PROCEDURE [dbo].[registrar]
@tipocuenta int,
@nom_usu varchar(50),
@pass varchar(50),
@pregunta varchar(50),
@respuesta varchar (50),
@email varchar(50)
AS
BEGIN
IF exists(select * from cuenta where cuenta.nombre_usuario=@nom_usu)
BEGIN
RAISERROR('Ya existe una cuenta de usuario asociado al ID ingresado',11,1)
END
ELSE
BEGIN
insert into cuenta (nombre_usuario,contraseña,id_tipo,pregunta,respuesta,email)values(@nom_usu,@pass,@tipocuenta,@pregunta,@respuesta,@email)
END
END
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "registrar";
cmd.Parameters.AddWithValue("@tipocuenta", 2004);
cmd.Parameters.AddWithValue("@nom_usu",txtnomreg.Text);
cmd.Parameters.AddWithValue("@pass", txtpass.Text);
cmd.Parameters.AddWithValue("@pregunta",Cbopreguntareg.SelectedItem);
cmd.Parameters.AddWithValue("@respuesta", txtrespuesta.Text);
cmd.Parameters.AddWithValue("@email", txtemailreg.Text);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
catch (Exception ex)
{
lblveripass.Text = ex.Message ;
}
hola Sandra
ResponderEliminarsi la idea es guardar solo una cadena que hag referencia a la imagen recuerda solo hacerlo con el nombre, o una ruta relativa, no lo hagas con una ruta fisica completa, o sea mueve la imagen a una carpeta conocida, podrias suar el
File.Copy()
la idea es que la ruta real para acceder a la imagen la armes dinamicamente, podrias suar el Application.StartUpPath para saber la ruta de la aplicacion y en una carpeta de imagenes poner todo alli, esto si la aplicacion se ejecuta local, o sino configurar una ruta en el app.config
despues guarda el nombre de la imagen es como cualquier otro parametro del tipo string, no hay diferencia
saludos
Intento como me explicas, pero no me funciona. Tienes algun ejemplo similar?
ResponderEliminarY sigo con el proble del error en el codigo que expuse arriba: "child list for field dtproductos cannot be created".
Será que le falta algo al codigo???
Hola Master Leandro,
ResponderEliminarÚltimamente he estado viendo tus artículos y me ha sorprendido el gran aporte que haces. Han servido de mucha ayuda.
Te un inconveniente que me gustaría consultar.
Es que necesito seleccionar de una BD un conjunto de artículos para editarlos, el problema está en que no sé cómo sacar uno de los campos de la tabla tipo imagen a un picture box.
Como le asigno el valor de ese campo imagen de la tabla a un picture box para editarlo.
Muchas Gracias
hola Sandra
ResponderEliminareste error que mencionas se produce cuando eejcutas desde el VS ? o es cuando haces el deploy
has analizado el StackTrace del Exception para poder ubicar donde se produce
saludos
hola Jose
ResponderEliminarpero es un desarrollo web el que estas realizando ? o es desktop
porque sino debrias analizar
[WinForms] Edición Empleados
alli recuperao la imagen y la muestro en un picturebox
saludos
Saludos Leandro
ResponderEliminarGracias, con este ejemplo lo pude hacer, gracias.
Hola denuevo Leandro
ResponderEliminarel error se produce cuando ejecuto desde el VS, pero lo analice con el StackTrace como me dijiste y ya detecte donde esta el error.
Gracias por la ayuda.
Hola leandro muy bueno tu post, lo estoy implementando en un formulario de productos, pero resulta que tengo inconvenientes con aquellos productos que no tienen imagenes. Ejemplo cuando busco determinado producto y de los resultados hay dos que no tiene fotos el primer registro lo decuelve con foto no disponible y el segundo lo trae sin imagen.
ResponderEliminarHola Leandro, Me gustan mucho tus publicaciones.
ResponderEliminarNecesito que me orentes en un inconveniente que se me ha presentado.
Esto creando un formulario de captura de productos y la mayoria se insertan bien, pero los de tipo decimal o double no lo hacen de la manera correcta pues parece que se redondean automaticamente.
Si cuando lo ejecuto introduzco por ejemplo un 5.89 en la base de datos se guarda un 6 y no lo guarda en forma decimal
y si coloco un 1.45 en la bd aparece guardado un 1.
No se por que pasa esto porque en el codigo de la captura lo especifico de esta forma:
cmd.Parameters.Add("@precioCompra", System.Data.SqlDbType.Decimal);
cmd.Parameters.Add("@utilidad ", System.Data.SqlDbType.Decimal);
cmd.Parameters.Add("@inpuestoVenta", System.Data.SqlDbType.Decimal);
y luego
cmd.Parameters["@precioCompra"].Value = Convert.ToDecimal(txtPrecioCompra.Text);
cmd.Parameters["@utilidad "].Value = Convert.ToDecimal(txtUtilidad.Text);
cmd.Parameters["@inpuestoVenta"].Value = Convert.ToDecimal(txtImpuestoVenta.Text);
Me prodrias deir que tengo que hacer para estos datos se capturen asi en forma decimal y noentero como lo estan haciendo?
Gracias.
hola andresfelipe
ResponderEliminarsi pones un breakpoint justo en el lugar donde evalua si el campo es dbnull o no
puedes validar que este sea nulo? porque podria ser que no sea nulo, pero la imagen este corrupta o grabada en el registro de forma incorrecta, por eso al recuperarla la realice de form incorrecta
podrias editar y probar asignar una nueva imagen, o dejar ese campo en nulo
saludos
hola Mario
ResponderEliminarhas validado la precision del campo en la tabla ? porque parece ser que se esta redondenando el valor
si por ejemplo haces
decimal precio =Convert.ToDecimal(txtPrecioCompra.Text);
y pones un breakpoint alli para evaluar el valor de la conversion, puedea validar que alli no se redondeo y los decimales se conservan ?
porque puede tambien ser un tema de cultura, valida que sea en-US para que toma el punto como decimal
saludos
Leandro, tengo dos registros en la base de datos el primero no tiene imagen, el segundo tiene imagen, depurando aparece tal cual esta en la bd.
ResponderEliminarcundo carga los datos en el datagridview y selecciono el que no tiene imagen y adjunto la imagen correspondiente, edito y cuando luego consulto de nuevo no aparece la imagen que seleccione si no que aparece la imagen de no disponible. pero esto pasa con algunas imagenes por que con otras da perfectamente. por ultimo abusando de tu gentileza, por que la razon de no guardar la imagen del no disponible como recurso del ensablado y no como una foto de bd. Gracias
Leandro como estas quisera saber como arrastar una imagen un documento word uno excel o un ppt a una grilla y gaudarlo en un base de datos en vb.net
ResponderEliminargracias
Hola Leandro me llamo Julio, quisiera que me des un ejemplo de como cargar una imagen, un word , un excel, un archivo de outlook o un ppt a un gGrid en vb.net con base de datos myql osea que se guarde
ResponderEliminarHola Leandro
ResponderEliminarTenias Razon el problema era la precision del campo en la tabla.
Muchas, Muchas Muchas Gracias!!!!!!
hola andres
ResponderEliminarla verdad esta bastante raro el problema, pareciera ser un problema en la logica de la aplicacion
si en lugar de visualizar la imagen en el picturebox la grabas como archivo usando
File.WriteAllBytes()
puede ver que se recupera correctamente de la db?
mas que nada para validar que en el registro se haya insertado la imagen que sabes seleccionaste para esa entidad
saludos
hola Julio
ResponderEliminarlo de arrastrar la verdad no sabria decirte
pero si defines alguna forma de selecciona usando el OpenfileDialog, podrias tomar se archivo he insertarlo en la db
http://social.msdn.microsoft.com/Forums/es/vsgenerales/thread/410c7ce0-058e-4dfc-8a08-a4f3cb1726f0
la tecnica para mysql es igual a cualquier otra db, si consigues el array de byte de la imagen puede asignarlo al parametro
saludos
Hola tutini este el blog esta muy bueno pero podrias hacer este mismo ejemplo pero usando Linq? es que soy nuevo y quiero aprender
ResponderEliminarhola Michael
ResponderEliminarcuando dices linq te refieres a Entity Framework ?
saludos
Me refiero al LINQ o Language INtegrated Query es una de las novedades más importantes de
ResponderEliminarMicrosoft .NET Framework 3.5 y que afecta por lo tanto a Visual Studio 2008 o versiones mayores.
SALUDOS
hola Michael
ResponderEliminarel tema es que con linq basico no se puede implementar lo que aqui estoy explicando
si se usa linq to sql, o entity Framework en ese caso si
pero linq de por si no persiste contra una db
saludos
creo que debebi especificarme bien jejejeje era con linq to sql me gustaria ver un ejemplo de lo que hiciste usando linq to sql si puedes hacerlo estaria agradecido
ResponderEliminarSaludos =)
hola
ResponderEliminarla verdad use casi nada linq sql ya que este es reemplazado por Entity Framework
estaba pensado armar algunos ejemplos con EF, no habia pensado ponerle tratamiento de imagenes, pero podria hacerlo
no has evaluado pasar a EF, es mas Code First esta genial
saludos
Si puedes armar un ejemplo con EF y con linq (aun que este obsoleto) seria genial me gustaria ver algo EF para ver como es
ResponderEliminarSaludo =)
hola
ResponderEliminarentonces voy a ver si me hago un rato el finde para terminar el articulo asi lo publico
saludos
Hola Leandro, saludos
ResponderEliminarMe ha surgido un problema que no he podido solucionar por más que lo intento.
Lo que pasa es que cuando intento llamar un formulario desde otro cualquira que sea el formulario que intento abrir se cierra antes de haber iniciado completamente, por ejemplo :
if (Nivel=="Administrador")
{Form2 f2=new Form2();
f2.Show(); }
de esta manera llamo x formulario según el tipo de usuario que inicia el sistema, el problema es que automáticamente abre el nuevo formulario que estoy llamando, en un abrir y cerrar de ojos se cierra, cualquiera que sea el formulario que intento abrir desde el login y no sé porque pasa esto porque he revisado las propiedades del nuevo formulario y no encuentro el problema. Además también he revisado el código en el login y no ordeno a cerrar desde que abran en ningún sitio.
Por qué podría estar pasando esto, me ayudas??
Gracias
hola Mario
ResponderEliminarestas definiendo algun codigo en el form_Load ? o en el constructor del form
que pasa si pones un breakpoint en el Load del form, ingresa la ejecucion alli ?
esto solo sucede con ese form, o es con todos lo mismo
saludos
Hola Leandro,
ResponderEliminarEsto me pasa en todos los formularios que llamo desde el form del login, he provado y parece que el problema esta en las sentencias close() porque cuando se las quito los form si cargan correctamente.
hola Sandra
ResponderEliminarpero implementas el login en el Main() ? porque si lo haces no necesitas de ningun close
como explico aqui
Login – Usando Password con Hash
como veras el login es previo a inicirse cualquier form
saludos
Una vez mas, eres un contribuidor de los buenos Leandro , muchas gracias.
ResponderEliminarHola saludos estoy usando la base de datos nortwind y trato de crear un nuevo registro en la tabla Categories mediante un winform pero el problema esta en que esta base de datos tiene una cabecera de 78 bits que hay q considerar a la hora de hacer el registro puedo extraer los datos para mostrarlos alguna idea de como hacer el registro?
ResponderEliminareste seria el codigo para recuperar los valos de la tabla categories
byte[] foto = (byte[]) this.dataGridView1.Rows[e.RowIndex].Cells["Imagen"].Value;
MemoryStream ms = new MemoryStream(foto, 78, foto.Length-78);
picFoto.Image = Image.FromStream(ms);
hola Alonso
ResponderEliminarimagino esto que planteas se relaciona con la pregunta en el foro
http://social.msdn.microsoft.com/Forums/es-ES/vcses/thread/92b6fbaa-9c44-4766-8417-7f06b8399bdc
saludos
Hola Leandro, hablando en 3 capas... porque se hace el diagrama de clases de un proyecto en base a las entidades?
ResponderEliminarcapa de datos, negocio, presentacion y entidades.. saludos
hola Si Señor
ResponderEliminarpartamos que el diagrama de clases modela las clases de la aplicacion, por lo que cada capa se la podria ver como una clase, despues de todo eso es justamente lo que se usa en cada proyecto
a su vez las entidades de negocio tambien son clases por lo que podria usarse el mismo diagrama
en realidad lo correcto seria que las capas en si se definan en un diagram de despliegue, pero esto solo es util si se va a utilizar capas remotas o si van a estar fisicamente en distintos equipos,
por lo general las capas con mas bien una separacion logica para dividir responsabilidads y mejorar el mantenimiento futuro
saludos
Leandro muy buenos dias muy interesante el codigo que nos muestras con esta solución. Fuera de este contexto tengo la siguiente pregunta como puedo enviar el foco hacia una ventana y qu esta ventana siempre la coloque hasta arriba sobre todas las ventanas
ResponderEliminarHola Leandro, entonces supongamos que tenemos las clases ProductoDAL, ProductoBLL, ProductoENT .. en el diagrama de clases se pondría un "Producto" y esa clase va a contener las propiedades de la entidad y los métodos de la clase DAL y la BLL o nada que ver?
ResponderEliminarEs un ejemplo.. saludos
hola Teckno
ResponderEliminarpodrias usar el metodo ShowDialog() para lanzar la ventana de forma modal y que quede por encima del resto, impidiendo acceder a las de abajo hasta que no la cierres
otra seria usar la propiedad
Form.TopMost Property
y una tercera opcion seria usando las api de windows con el SetWindowPos
saludos
hola Si Señor
ResponderEliminaren realidad cada una de esas clases actura de forma independente, implementando su responsabilidad
quizas deberias analizar:
[N-Tier] – Desarrollo en capas - Ejemplo Facturación – Parte 3
alli se explica mejor el tema de capas, si quieres antes analiza las primeras partes asi puede ver toda la evolucion
saludos
Hola leandro, buen tutorial, una pregunta, en lugar de usar codigo linq en asignarestudios(), se podria trabajarlo de otra manera creando algun store procedure o similares, sucede que no uso mucho linq, agradecere tu respuesta
ResponderEliminarhola mel
ResponderEliminarel tema es que alli estas uniendo un control grid contra los datos procedientes de una db, no se puede hacer desde una simple query porque no tendrias acceso al control para saber que item marcar
se podria hacer dos foreach, se toma un item del datagridview y se recorre el datarable para ver si alguno coincide y si es asi se marca, luego se pasa el siguiente
linq internamente hace algo como es, mucho mas optimo por supuesto, pero bueno sino te animas a linq seria la alternativa,
aunque aconsejaria te animes, cuando entiendas linq puedo asegurarte que no lo dejas nunca mas
101 LINQ Samples
LINQ to Objects
saludos
Hola Leandro quiero llevar este ejemplo a web, pero en el caso del datagridview, seria similar al gridview?, lo digo por el codigo mas que nada puesto que mas he usado ha nivel windows y nesecito uno en web, no se si podrias darme una ayudita en esta parte, por favor, saludos
ResponderEliminarhola mel
ResponderEliminarentonces revisa el otro articulo
[ASP.NET] GridView – Edición Empleados
saludos
Hola Sandra,
ResponderEliminarpara el problema de la carga del DataGridView: prueba a no informar la propiedad DataMember a ver si se resuelve tu problema.
Si sólo le pasas una tabla en el DataSource no es necesario que indiques ningún valor a la propiedad DataMember.
(Framework .NET 4.0)
Saludos!
Jesús.
muy bueno el tutorial, en algun momento pasaras a hacer tutoriales con bases de datos de mysql?
ResponderEliminarhola 4º secretariado C
ResponderEliminarel tema es que conociendo ado.net la base de datos que se utilice no es importante ya que ado.net es igual para todas las db
quizas cambien algunos detalles, como ser la definicion de los parametros en sql server usas "@" y en mysql usas "?"
pero mas alla de eso el resto es practicamente igual
estaba pensando armar articulos sobre ado.net que muestren como trabjar con Sql Server, Mysql y Oracle, tengo que ver como estructuro el tema
saludos
Gracias por este valioso aporte, me ha servido en gran manera la forma en como utilizas la clase ImageHelper.cs. Te agradesco y te mando saludo desde Nicaragua
ResponderEliminarHola Leandro gracias por el aporte pero tengo una gran duda, por ejemplo a mi me solicitan constantemente que muestre otros campos de los foreign keys, te hago un ejemplo:
ResponderEliminarclass Cliente{
public string Nombre;
public string Apellido;
public int IdTipoCliente;
}
class TipoCliente{
public int IdTipoCliente;
public string TipoCliente;
}
Y desean ver una lista de clientes que muestre los campos:
Nombre, Apellido, TipoCliente(el texto segun el id que es IdTipoCliente).
¿Esto en ASP.NET como podría listarlo en el gridview?
Gracias.
hola Bryan
ResponderEliminarhay dos formas de implementar lo que planteas
- aplanando la entidad y creando una clase que sea
class Cliente{
public string Nombre;
public string Apellido;
public int IdTipoCliente;
public int TipoClienteDesc {get;set;}
}
entonces en la misma entidad traes el id y la descripcion de la entidad relacionada
por supuesto a nivel de db esto lo resuleves con un INNER JOIN
- la otra es relacionar las entidades, permitiendo una relacion de asociacion entre estas
class Cliente{
public string Nombre;
public string Apellido;
public int IdTipoCliente;
public TipoCliente TipoCliente {get;set;}
}
como veras la clase Cliente tinee una propiedad del tipo TipoCliente, para cargar esta entidad podrias hacer
n-Layer - SchoolManager - Herencia y navegación de entidades relacionadas (2/2)
Nota: lo que si recomendaria es que uses propiedades y no variables publicas
saludos
Gracias Leandro, lo estaré viendo, una consulta sé que estos tips lo aprendiste con la experiencia pero crees que haya algún libro, manual o web, donde pueda leer sobre estas teorías que me faltan aprender, me gusta saber el porque y para que se debe usar así.
ResponderEliminarGracias nuevamente, un saludo cordial desde Perú.
hola
ResponderEliminarpodrias ver sobre este tema aqui
Centro de Arquitectura - MSDN
saludos
Leandro una consulta.. cuando agrego algo al ejemplo asi sea un label.. me escribe en el codigo handles a los botones y eso hace un error estoy en vb2008 con sql server express 08
ResponderEliminarsi le saco lo de handless se desabilitan los botones??? tendras alguna idea???
hola Luis
ResponderEliminarpuede ser que sin querer estes realizando doble click en el control que agregas y esto hace que se cree el evento por defecto que tiene ese control
o sea si al colocar un control cualquiera le haces doble click iras al codigo y se creara el evento por defecto
aunque es raro que un label cree una asociacion con el evento de un boton porque no tienen nada que ver uno con otro
si revisas los eventos, selecciona el control y presiona F4 para ver sus propiedades, despues ve al icono con forma de rayo amarillo y asi listar los eventos, puedes ver que se asocio de forma incorrecta el evento
saludos
Gracias, leandro ante todo quiero felicitarte por toda la info que tienes de .net eres de gran ayuda para los novatos (me incluyo) , volviendo al tema solo si hago doble click en los botones se desenlaza ya me acople al ejemplo de maravilla
ResponderEliminarhola Luis
ResponderEliminarentonces pudiste definir el evento?
si desde el diseñador es con doble click en el control que genera el codigo del evento por defecto
saludos
Hola leandro una consulta, en este ejemplo estas usando solo 2 capas cierto?? la de datos y la de interfaz? o la helper viene siendo la 3ra (logica)?
ResponderEliminarMe queda clara la de datos e interfaz pero helper no.
Otra cosa leyendo dicen que las aplicaciones en capas van perdiendo rendimiento, es verdad?? te ha pasado??
Gracias
Exelecete tus aporte, toy buscando de como utilizar un scanner con VB.NET o C# tendras un ejemplo o guia. no encuentro como utilizar
ResponderEliminarhola CRISTIAN
ResponderEliminarexacto en este caso solo son dos capas
el helper no es la capa de negocio
[N-Tier] – Desarrollo en capas - Ejemplo Facturación – Parte 3
en este otro articulo si veras la implementacion de 3 capas
hasta donde se no deberian perder nada si es que armas bien la arquitectura, si programas mas tengas 1,2 o 3 capas el rendimiento lo vas a perder, pero no es por la arquitectura sino porque esta mal diseñado
saludos
hola Jordan
ResponderEliminarpodrias suar las librerias de WIA o TWAIN
http://social.msdn.microsoft.com/Forums/es-ES/4218281e-4444-4443-9902-0f8643cf2660/obtener-imagen-desde-scanner-directamente-a-imagen-o-pdf-sin-utilizar-el-asistente?forum=vcses
en la pregunta del foro respondo sobre este mismo tema
saludos
hola leandro yo estoy implementando esos mismo procedimientos pero para un sistema de autos, aqui te pongo el codigo para que me digas por favor por que me da error en esas 3 lineas
ResponderEliminarprivate static Autoacces AgregarNuevo(Autoacces auto)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SistemadeAutos"].ToString()))
{
conn.Open();
string query = @"INSERT INTO catalogo (Marca, Año, Transmision, Recomendaciones, Imagen)
VALUES (@Marca, @Año, @Transmision, @Recomendaciones, @Imagen);
SELECT SCOPE_IDENTITY()";
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("@Marca", auto.Marca);
cmd.Parameters.AddWithValue("@Año", auto.Año);
cmd.Parameters.AddWithValue("@Transimision", auto.Transmision);
cmd.Parameters.AddWithValue("@Recomendaciones", auto.Recomendaciones);
SqlParameter imageParam = cmd.Parameters.Add("@Imagen", System.Data.SqlDbType.Image);
imageParam.Value = auto.Imagen;
//
// se recupera el id generado por la tabla
//
//en esta fila me da error// auto.Marca = Convert.ToInt32(cmd.ExecuteScalar());
}
private static Autoacces Actualizar(Autoacces auto)
{
//aqui me da error//using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SistemadeAutos"].ToString()))
{
conn.Open();
public static Autoacces Save(Autoacces auto)
{
using (TransactionScope scope = new TransactionScope())
{
//
// Graba datos empleado
//
//aqui me da error// if (Existe(auto.Marca))
Actualizar(auto);
else
AgregarNuevo(auto);
como veras solo puede los 3 lugares donde me da el error ya que el codigo es muy grande
ResponderEliminarhola Joel
ResponderEliminarpero no mencionaste cual es el mensaje de error que obtienes
veo el codigo y parece estar todo correcto
saludos
Hola que tal Leandro te saludo desde Ecuador , sabes la mayoría de tus blog me han sido de gran utilidad, y lo q estas publicando es lo q justamente necesito, como guardar imágenes, pero en este caso al guardar utilizo un stored procedure que desde la base de datos sql esta creado… el problema está en como adapto tu código de almacenar imagen a mi línea de sentencia, ya que tú lo envías como tipo de dato image , aunque si deseo guardar la imagen con ese tipo, pero no sé cómo adaptarle en este caso. Ojala me puedas ayudar o dar una sugerencia, a continuación te pongo como está el código.
ResponderEliminarDesde ya te doy gracias por el tiempo que dedicas a ayudarnos ..
Module Module1
'// Declaracion de variable globales para la conexion
Public conexion As SqlClient.SqlConnection
Public com As SqlClient.SqlCommand, dr As SqlClient.SqlDataReader
Public da As SqlClient.SqlDataAdapter, cb As SqlClient.SqlCommandBuilder
End Module
---------------------------------------
ced = txced.Text
nom = UCase(txtnombre.Text)
ape = UCase(txtapellido.Text)
dir = UCase(txtdireccion.Text)
fec_nac = DateTimePicker1.Value.ToString("yyyy-MM-dd")
sql = "exec guardar_paciente '" + ced + "','" + nom + "','" + ape + "','" + dir + "','" + fec_nac + "','" + foto + "'"
conectar()
com = New SqlClient.SqlCommand(sql, conexion)
res = com.ExecuteNonQuery
conexion.Close()
hola mary
ResponderEliminarla resolucion utilizando procedure es la misma que aqui planteo, solo que no debes usar el exec para invocar a un procesure sino que seria
using (SqlConnection conn = new SqlConnection("connectionstring"))
{
SqlCommand cmd = new SqlCommand("NombreProcedure", conn);
cmd.CommandType = SqlCommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@param1", valor);
cmd.ExecuteNonQuery();
}
la idea es que si defines el commandtype no necesitas del exec, por lo tanto asignas el parametro a la coleccion Parameters del Sqlcommand
saludos
Que tal Leandro, Un buen dia por fa talvez me puedas ayudar con lo siguiente: Estoy generando la impresion de unas facturas pero al momento de realizar esto se saturan los pools del IIS 7 y no permite que ningun usuario pueda realizar ninguna accion con la aplicacion para solventar esto tengo que ejecutar un recycle a los pools o en su defecto un IISRESET. La consulta es talvez tu conoces como liberar los pools desde el programa una vez terminado de imprimir las facturas????? O que puedo hacer para que no se presente este problema. Adicional te comento que se encuentra configurado para que se ejecute automaticamente el recycle cada dia, no puedo configurar para que se ejecute cada 10 o 15 min ya que esto conllevaria a que cada vez que realice les bote de las sesiones a los usuarios. De antemano Muchas gracias por tu ayuda... Saludos
ResponderEliminarhola Mario
ResponderEliminarentiendo que es un desarrollo web, pero me pregunto porque imprimes directo desde el servidor?
porque no generas el reporte, lo envias al cliente para que lo descargue y que este lo imprima desde su pc local, no veo como buena idea que un server web deba tener conectada una impresora
sino podrias tambien realizar un proceso separado al iis para estas impresiones, quizas un servicio de windows (el cual podria estar en el mismo servidor) y que el sitio web lance la accion de impresion para que ese otro proceso se encargue sin molestar al server web
es mas ese servicio hasta podria estar en una pc separada
saludos
Gracias Leandro, fue de gran utilidad tu respuesta ,pude solucionar el problema... gracias
ResponderEliminarHola Leandro muy buena explicación, te hago una consulta se podría asociar para un cliente varias imágenes? debería crearse 2 tablas?
ResponderEliminarel tema es que yo quiero consultar para un cliente las imagenes que tiene almacendas. Gracias
hola TECSECA
ResponderEliminaren este caso la tabla de empleados se diseño con un campo de imagen por lo que solo podras contener una
ahora bien si se quiere definir dos se podria simplemente agregar un campo adicional
aunque si se prevee que puede tener N imagenes se podria crear una tabla que tenga los campos
EmpleadoImagenes(tabla)
ImageId PK
EmpleadoId FK
Imagen
esta table se unira uno a muchos con la de empleados
saludos
Gracias por tu respuesta. Ahora bien, de acuerdo a mi consulta entiendo que tu respuesta seria para para adaptar a tu ejemplo. La nueva tabla a crear sera lo mas eficiente al parecer, pero la verdad no se me ocurre el codigo para adaptarlo a tu ejemplo. Me podrias orientar por favor. Muchas Gracias
ResponderEliminarhola TECSECA
ResponderEliminarpero es codigo implicaria recorrer la lista de imagenes que tienes que persistir y realizar tantos INSERT como imagenes tendra
seria poner en un loop el insert que harias con una sola imagen
insertar una imagen como explico en este articulo imagino quedo claro, no ? bueno insertar varias en esta table seria ejecutar el INSERT de una imagen varias veces
saludos
Hola, soy nuevo en programación (vb). Me gustaría saber como puedo la imagen de un picturebox, previamente cargada de webcam, guardarla en base de datos access y después, cuando la necesite verla en el picturebox. Gracias de antemano
ResponderEliminarHola quisiera que me ayudes en un sistema pequeño que estoy haciendo quiero guardar imagenes en una base de datos de access con vb. net 2010 y que esas imagenes se carguen en un datagridview. Gracias de antemano
ResponderEliminarhola
EliminarPero no hay mucha diferencia en el codigo que implementarias entre sql server o access (en ambos usarias ado.net), quizas lo que cambie es el tipo de dato que defines en la tabla
En ambos casos defienes parametro y envias un array de byte del archivo
saludos
Hola leandro en mi caso yo uso 3 capas, y lo que quiero hacer es guardar una foto del empleado en mi base de datos de sql lo cual mi campo es de tipo IMAGE. y quiero hacerlo a travez de procedimientos almacenados juntamente con un picturebox y un openfiledialog en mi form de C# podrias ayudarme con un codigo mas sencillo por favor, esto es para una tarea de la Universidad. mi codigo en mi capa de conexion es el siguiente:
ResponderEliminarpublic class SQLHelper
{
public DataTable ExecuteDataQuery(String NombreSP, params object[] ParamArray)
{
String strcone = "Integrated Security=true; Initial Catalog=BHCARDENAS;server=.";
SqlConnection cn = new SqlConnection(strcone);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = NombreSP;
cn.Open();
SqlCommandBuilder.DeriveParameters(cmd);
int i = 0;
foreach (SqlParameter p in cmd.Parameters)
{
if (p.ParameterName != "@RETURN_VALUE")
{
p.Value = ParamArray[i];
i++;
}
}
cn.Close();
SqlDataAdapter da;
da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
//GRABA
public String ExecuteUpdateQuery(String NombreSP, params object[] ParamArray)
{
String result = "";
try
{
String strcone = "Integrated Security=true; Initial Catalog=BHCARDENAS;server=.";
SqlConnection cn = new SqlConnection(strcone);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = NombreSP;
cn.Open();
SqlCommandBuilder.DeriveParameters(cmd);
int i = 0;
foreach (SqlParameter p in cmd.Parameters)
{
if (p.ParameterName != "@RETURN_VALUE")
{
p.Value = ParamArray[i];
i++;
}
}
cmd.ExecuteNonQuery();
cn.Close();
result = "Operacion Exitosa";
}
catch (Exception ex)
{
result = "Error en SP" + ex.Message;
}
return result;
}
espero que puedas ayudarme, gracias saludos.
hola
Eliminarte estas equivocando cuando defines ExecuteDataQuery() no deberias indicar los parametro como array de object, sino que deberian ser un array de SqlParameter
public DataTable ExecuteDataQuery(String NombreSP, params SqlParameter[] sqlParams){ ...
de esta forma cuando indicas los datos desde fuera puedes crear el parametro del tipo imagen y asignar el array de byte de la imagen que quieres insertar
Es mas para hacerlo mas simple usaria
public DataTable ExecuteDataQuery(String NombreSP, List sqlParams){ ...
una lista generica
Una aclaracion definir este helper no quiere decir que uses 3 capas, el helper no representa la capa de persistencia, para eso deberias implementar el patron Repository
saludos
Que tal Leandro, estoy diseñanado un sistema en vb.net, solo que no se muy bien lo de las clases y metódos utilizados al igual que no se no se como se hacen los procemientos almacenados, yo solo inserto directo mi codigo en vb. Por esta razón queria pedirte tu ayuda para solucionar el error en en que me encuentro al no poder insertar una imagen.
ResponderEliminarEste es el codigo que utilizo en esta parte declaro mi variable,
Dim vimgn As New IO.MemoryStream()
If ptbimagen.Image Is Nothing Then
ptbimagen.Image.Save(vimgn, ptbimagen.Image.RawFormat)
Else
ptbimagen.Image = My.Resources.fondo
ptbimagen.Image.Save(vimgn, ptbimagen.Image.RawFormat)
End If
Aca inserto entre otros mis registros y el de imagen
With cmd
.Connection = conexion
.CommandText = " INSERT INTO Compras (idemisor, No_Compra, Pdf, Xml_, Impreso, JpgPdf) " &
" VALUES (" & idemi & ", '" & noComp & "', '" & vpdf & "', '" & vxml & "', " &
" '" & vimpre & "', '" & ptbimagen.ImageLocation & "')"
i = cmd.ExecuteNonQuery
End With
Realizo una trazo y esto es lo que me devuelve
INSERT INTO Compras (idemisor, No_Compra, Pdf, Xml_, Impreso, JpgPdf) VALUES (2, 'A', 'SI', 'SI', 'SI', '')
Y aca es donde no me trae datos de la imagen.
al parecer creo que es en esta parte '" & ptbimagen.ImageLocation & "', no se que metódo o clase utilizar para que me devulva algo.
Espero puedas ayudarme.
Saludos
Hola, queria saber que diferencia habria entre que el EmpleadoEntity en vez de tener un EstadoCivil de tipo entero, tuviese un EstadoCivil de tipo EstadoCivilEntity. y como seria si quisiese mostrarlo en el datagridview de lista de empleados
ResponderEliminarPor otro lado ¿que deberia hacer si quisiese mostrar en el datagridvew el id de empleado en el sguente formato: EMP-0001? Estuve intentando esto: row.Cells["id"].Value = "EMP-" + item.id.ToString("0000"); pero me dice que solo puedo asignar un valor de tipo entero
hola
EliminarLa diferencia entre un estado civil como entidad es de dodne obtienes la lista para cargar el combo que listas al usuario, despues el resto es igual
Para mostrarlo en el grid vas a tener que definir el INNER JOIN en el SELECT y devolver el nombre o descripcion de ese estado como respuesta
si usas clases podrias definir este strinf directo alli
public string IdDesc { get { return string.Format("EMP-{0:0000}", this.Id); } }
esta propiedad de solo lectura la defines dentro de la clase y la usas para bindear con el campo del grid
saludos
Y como haria si quisiese mostrar los estudios en un campo del datagrdview principal (el de la lista de empleados) de esta forma: "primaria, secundaria, superior", es decir, en un solo campo separados por comas
ResponderEliminarEn este caso vas a tener que armar una query sql que permita agrupar por estos campos y unirlos en uno solo
EliminarGROUP BY clause to get comma-separated values
saludos
Pero si la query llega con todos los estudios de los empleados en una celda, como pasaria de la query a objetos: EmpleadoEntity y EstudioEntity para luego pasar la lista de EmpleadoEntity al datagridview mostrando los nombres de los estudios alli?
Eliminarhola
EliminarEn el DataGridView no vas a poder mostrar objetos complejos, es por eso que una lista no aplica en el grid, podrias si en la clase EmpleadoEntity crear una propiedad readonly que usea la propiedad de lista de estudios y genere un string con los estudios separados por coma, usando esta nueva propiedad de solo lectura en el campo del control grid
saludos
Como deberia ser el stored procedure en la base de datos para asignar los estudios a los empleados? ¿sera posible enviar por parametro al stored procedure de "crear empleado", un array de los id de los estudios para luego asignarle a ese empleado todos sus estudios en un solo procedimiento o se tiene que hacer de obligado una llamada por cada estudio a un procedimiento que asigne estudios uno por uno?
ResponderEliminarhola
EliminarPodrias enviar a un procedure la lista de ids de estudios que quieres relacionar con el empleado, para eso usarias el
Table-Valued Parameters in SQL Server 2008 (ADO.NET)
con un table-valued podrias envias datos en formato array, tambien podrias enviar un xml con la lista
saludos
Hola leandro, como podria actualizar los datos si los dos formularios lo tengo en uno solo?
ResponderEliminarhe intentado hacerlo de la manera en que describes en tu ejemplo pero no he podido hacerlo.
Este comentario ha sido eliminado por el autor.
ResponderEliminarEs decir todo lo quiero realizar en un solo formulario, yodo va bien hasta el momento de hacerle doble click para pasar a editarlo.
ResponderEliminarcuando hago esa operación me abre nuevamente el formulario y eso es lo que no deseo, en vez que me abra otro formulario que lo actualice ahí mismo.
Este comentario ha sido eliminado por el autor.
ResponderEliminarExcelente tutorial, después de tanto tiempo agradezco que siga vigente
ResponderEliminarHola ¿Das clases particulares? Leo tus blog hace meses y me gustaría tomar clases.
ResponderEliminar