Introducción
Al momento de relacionar entidades algunas pueden necesitar asociarse con colecciones de otras entidades, pero que sucede cuando esto se necesita en ambas direcciones?, es aquí donde entran las relaciones mucho a muchos, en donde a nivel de base de datos se va a requerir de una tabla intermedia para poder implementar la relación.
En este articulo veremos como lograr esta asociación y analizaremos que pasa a nivel de base de datos, el objetivo final será lograr un modelo de objeto como el siguiente:
y su equivalente en el modelo de datos:
Definición de las entidades
En el proyecto “Entities” serán definidas las clases que modelan los empleados y territorios, cada uno define una propiedad del tipo colección hacia a otra.
public class Territory { public int TerritoryID { get; set; } public string TerritoryDescription { get; set; } public virtual ICollection<Employee> Employees { get; set; } }
public class Employee { public int EmployeeID { get; set; } public string LastName { get; set; } public string FirstName { get; set; } public string Address { get; set; } public string City { get; set; } public string Region { get; set; } public string PostalCode { get; set; } public string Country { get; set; } public virtual ICollection<Territory> Territories { get; set; } }
Definición del contexto
La clase de context, la cual hereda de Dbcontext, define las propiedades que representan cada entidad, utilizando el tipo DbSet<>.
La sobrecarga del método OnModelCreating será el responsable de la configuración del mapping, para que no quede toda el código junto en un solo sitio y sea mantenible en el tiempo se hará uso de clases separadas para cada entidad, estas clases heredan de EntityTypeConfiguration<>.
public class NorthWindContext : DbContext { public NorthWindContext() : base("NorthwindDb") { this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; } public DbSet<Territory> Territories { get; set; } public DbSet<Employee> Employees { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new TerritoryMap()); modelBuilder.Configurations.Add(new EmployeeMap()); base.OnModelCreating(modelBuilder); } }
En este caso se decidió utilizar la entidad del territorio para definir la relación mucho a muchos, esto se logra definiendo el HasMany()
La relación requiere definir el nombre que tendrá la tabla intermedia, así como los campos claves que actuaran en la relación.
public class TerritoryMap : EntityTypeConfiguration<Territory> { public TerritoryMap() { HasKey(x => x.TerritoryID); Property(x => x.TerritoryDescription).HasColumnType("nchar").HasMaxLength(50).IsRequired(); HasMany(x => x.Employees) .WithMany(x => x.Territories) .Map(mc => { mc.MapLeftKey("TerrytoryID"); mc.MapRightKey("EmployeeID"); mc.ToTable("EmployeeTerritories"); }); } }
Nota: la definición de la relación no era obligatorio hacerlo en la entidad Territory, se podría haber realizado en la clase Map del Employee sin ningún problema, solo hay que tener en cuenta cambiaran las definiciones de MapLeftKey() y MapRighKey()
El empleado define el mapeo normalmente
public class EmployeeMap : EntityTypeConfiguration<Employee> { public EmployeeMap() { HasKey(x => x.EmployeeID); Property(x => x.LastName).HasMaxLength(20).IsRequired(); Property(x => x.FirstName).HasMaxLength(10).IsRequired(); Property(x => x.Address).HasMaxLength(60); Property(x => x.City).HasMaxLength(15); Property(x => x.Region).HasMaxLength(15); Property(x => x.PostalCode).HasMaxLength(10); Property(x => x.Country).HasMaxLength(15); } }
Especialización del repositorio
Para poder operar con las colecciones se requiere estar dentro del contexto de EF, pero sucede que la implementación del repositorio desconecta las instancias de las entidades al devolverás para poder ser usadas desde fuera por lo tanto aplicar cambios en estas no ejecutara las acciones de actualización de forma correcta.
Es aquí donde se requiere personalizar el repositorio, por ejemplo en el repositorio del territorio definir métodos que permiten agregar o quitar empleados.
Si bien los parámetros de estos métodos son tipos de cada entidad, se podrían haber utilizado solo los IDs de las mismas
public class TerritoryRepository : BaseRepository<Territory> { public void AddEmployees(Territory territory, List<Employee> employes) { using (NorthWindContext context = new NorthWindContext()) { //marcamos el territorio para que no reciba cambios context.Entry(territory).State = EntityState.Unchanged; if (territory.Employees == null) territory.Employees = new List<Employee>(); //recorremos cada empleado que se quiera asociar employes.ForEach(x => { //el empleado tampoco debe recibir cambios context.Entry(x).State = EntityState.Unchanged; //asociamos a la colecion de empleados del territorio el nuevo item //este si recibira cambios territory.Employees.Add(x); }); context.SaveChanges(); } } public void RemoveEmployees(Territory territory, List<Employee> employees) { //validamos que haya algo que remover if (employees == null || employees.Count == 0) return; using (NorthWindContext context = new NorthWindContext()) { //recuperamos el terrotorio y sus empleados //esto es necesario porque el objeto donde se debe remover tiene que estar dentro del contexto de EF Territory territorySel = context.Set<Territory>().Include("Employees").FirstOrDefault(x => x.TerritoryID == territory.TerritoryID); if (territory.Employees == null || territory.Employees.Count == 0) return; employees.ForEach(x => { //localizamos al empleado dentro de la coleccion que se recupero anteriormente Employee employeeRemove = territorySel.Employees.First(e => e.EmployeeID == x.EmployeeID); //se remueve de la coleccion haciendo uso de la instancia territorySel.Employees.Remove(employeeRemove); }); context.SaveChanges(); } } }
Test – Obtener territorio con empleados asociados
Empezaremos con un test simple, en donde solo se relacionen las entidades y puedan recuperarse
[TestMethod] public void Get_ListEmployee_Territory() { TerritoryRepository repoTerritory = new TerritoryRepository(); Territory territoryNew = new Territory() { TerritoryDescription = "territoty 1", Employees = new List<Employee>() { new Employee() { FirstName = "Name 1", LastName ="LastaName 1" }, new Employee() { FirstName = "Name 2", LastName ="LastaName 2" } } }; repoTerritory.Create(territoryNew); var territorySel = repoTerritory.Single(x => x.TerritoryID == territoryNew.TerritoryID, new List<Expression<Func<Territory,object>>>(){ x=>x.Employees }); Assert.IsNotNull(territorySel); Assert.IsNotNull(territorySel.Employees); Assert.AreEqual(territorySel.Employees.Count, 2); }
La creación del territorio implicara varias acciones como puede observarse en la captura del profiler
Se insertan los empleados, a continuación el territorio y por ultimo los registros que relacionan ambas entidades
Para recuperar las relaciones es necesario definir la propiedad como parte del Include()
En una sola instrucción SELECT se recuperan el territorio y los empleados asociados a esta.
Test – Agregar empleados a territorio existentes
Seria muy raro que al momento de crear un territorio se disponga de los empleados que se asocian al mismo, y solo estos conformen la relación, lo común es tener entidades independientes y asociarlas de forma dinámica, por lo general mediante acciones del usuario en la aplicación.
[TestMethod] public void Update_ExistingEmployee_Territory() { TerritoryRepository repoTerritory = new TerritoryRepository(); EmployeeRepository repoEmployee = new EmployeeRepository(); //se crean los empleados Employee employeeNew1 = new Employee() { FirstName = "Name 1", LastName ="LastaName 1" }; repoEmployee.Create(employeeNew1); Employee employeeNew2 = new Employee() { FirstName = "Name 2", LastName ="LastaName 2" }; repoEmployee.Create(employeeNew2); //se crea el territorio Territory territoryNew = new Territory() { TerritoryDescription = "territoty 1" }; repoTerritory.Create(territoryNew); //asignamos los empleados al territorio existente repoTerritory.AddEmployees(territoryNew, new List<Employee>(new Employee[]{ employeeNew1, employeeNew2 })); //validamos que la asignacion se haya realizado correctamente //recuperando la entidad y sus relaciones var territorySel = repoTerritory.Single(x => x.TerritoryID == territoryNew.TerritoryID, new List<Expression<Func<Territory, object>>>() { x => x.Employees }); Assert.IsNotNull(territorySel); Assert.IsNotNull(territorySel.Employees); Assert.AreEqual(territorySel.Employees.Count, 2); }
La primer parte de la ejecución del test crea las entidades de forma independiente
Luego se añade los empleados al territorio
y al final para validar que todo este correcto recuperando el territorio y su relación con los empleados
Test – Remover un empleado asociado
Hasta el momento hemos agregando entidades a la colección, pero es muy común querer quitarlas, para esto haremos uso del método creado especialmente en el repositorio de la entidad Territorio.
Antes de seguir hay que aclarar que la estructura de las tablas que crea Entity Framework desde el modelo asigna en las relaciones la opción de borrado en cascada, es necesario conocer esto si es que se quiere eliminar una entidad completa, ya que el hacerlo provocara que todas las asociaciones que esta tenga también sean eliminadas
Veamos el código del test que remueve un empleado en concreto de la colección
[TestMethod] public void Delete_AssignedEmployee_Territory() { TerritoryRepository repoTerritory = new TerritoryRepository(); EmployeeRepository repoEmployee = new EmployeeRepository(); //se crean los empleados Employee employeeNew1 = new Employee() { FirstName = "Name 1", LastName = "LastaName 1" }; repoEmployee.Create(employeeNew1); Employee employeeNew2 = new Employee() { FirstName = "Name 2", LastName = "LastaName 2" }; repoEmployee.Create(employeeNew2); //se crea el territorio Territory territoryNew = new Territory() { TerritoryDescription = "territoty 1" }; repoTerritory.Create(territoryNew); //asignamos los empleados al territorio existente repoTerritory.AddEmployees(territoryNew, new List<Employee>(new Employee[] { employeeNew1, employeeNew2 })); //validamos que la asignacion se haya realizado correctamente //recuperando la entidad y sus relaciones var territorySel = repoTerritory.Single(x => x.TerritoryID == territoryNew.TerritoryID, new List<Expression<Func<Territory, object>>>() { x => x.Employees }); Assert.IsNotNull(territorySel); Assert.IsNotNull(territorySel.Employees); Assert.AreEqual(territorySel.Employees.Count, 2); //removemos uno de los empleados asignados repoTerritory.RemoveEmployees(territoryNew, new List<Employee>(new Employee[] { employeeNew1 })); //recuperamos el territorio para validar que se haya eliminado el empleado var territorySel2 = repoTerritory.Single(x => x.TerritoryID == territoryNew.TerritoryID, new List<Expression<Func<Territory, object>>>() { x => x.Employees }); Assert.IsNotNull(territorySel2); Assert.IsNotNull(territorySel2.Employees); Assert.AreEqual(territorySel2.Employees.Count, 1); Employee employeeSel = territorySel2.Employees.First(); Assert.AreEqual(employeeSel.FirstName, employeeNew2.FirstName); Assert.AreEqual(employeeSel.LastName, employeeNew2.LastName); }
La primer parte es idéntica al Test anterior, se crean las entidades individualmente, se asignan los empleados al territorio y se validad que todo se haya realizado correctamente.
Luego se procede a quitar uno de los empleados, ejecutándose la instrucción SQL que remueve el registro
Documentación de referencia
Associations in EF Code First: Part 6 – Many-valued Associations
Configuring a Many-to-Many Relationship
Código
Se utilizo Visual Studio 2012, no se adjunta ninguna base de datos, esta será creada al ejecutar los test utilizando el modelo definido en el contexto de EF.
[C#]
|
Gracias Leo!!!
ResponderEliminarTe pregunto : que marques el territorio y los empleados como unchanged a la hora de agregar, hace que no se vuelvan a agregar porque ya existen, no?
Si es asi yo no podria mandar como paramatros un territorio y empleados que solo esten en memoria y no hallan sido creados anteriormente?
Otra vez gracias, son muy utiles tus articulos y muy entendibles!!!
hola Patos
ResponderEliminarexacto el poner la entidad como unchanged evita que se vuelva a crear
cuando dices que estan en memoria apuntas a que son entidades que estan dentro del contexto, o son entidades desconectadas ? porque hay que aclarar que aqui al usar el repositorio las entidades son desoconectadas del contexto por eso es que se vuelven adjuntar cuando se realiza el Entry()
la idea es que esta accion solo permite relacionar entidades, si quieres actualizarlas solo usas el metodo Update() comun aplicando el cambio a la entidad en particular
saludos
claro Leo yo decia desconectadas, pero si ya me sacaste la duda!
ResponderEliminarGracias!!
Hola, tengo una duda
ResponderEliminar¿Se podría crear una columna más a la tabla de relación EmployeeTerritories??
Saludos
hola DaNny
ResponderEliminarel tema es que si agregas una columna deja de ser una relacion mucho a mucho de forma que la tabla intermedia es transparente y oculta en el modelo
la entidad pasa a tomar peso y ser una entidad nueva que relaciona dos entidades
deberas crear la clase que representa la tabla intermedia para poder ponerle esa propiedad
saludos
Hola Leandro, muy buen post!
ResponderEliminarEstoy tratando de implementar el repositorio (“IRepository” y “BaseRepository”) en una aplicación Visual Basic, me podrás ayudar a convertir esta función que no la puedo resolver?
En IRepository:
T Single(Expression> predicate, List>> includes);
En BaseRepository:
public T Single(Expression> predicate, List>> includes)
Y si no fuera tanta molestia, como la llamaría desde el cliente?
var categorySelected = repoCategory.Single(x => x.CategoryID == categoryNew.CategoryID, new List>>() { x=>x.Products });
Intente utilizar el conversor (http://www.developerfusion.com/tools/convert/csharp-to-vb/) pero me da error.
Las funciones de crear, actualizar y eliminar me anduvieron bien. Tambien la que devuelve la lista completa y el single simple.
Muchas gracias!!!
hola Jorge
ResponderEliminarla conversion podria ser
Public Function Single(Expression(Of Func(Of T, Boolean)) predicate) As T
y luego para usarlo
Dim categorySelected = repoCategory.Single(Function(x) x.CategoryID = categoryNew.CategoryID, New List(Of Expression(Of Func(Of Territory,object))) { Function(x) x.Employees} )
estas converisones las realice directamente y no las probe en codigo, quizas le falte algun With en algun punto
por como veo que queda la escritura de este codigo me parece que va a ser mas facil que aprendas c#
saludos
Gracias Leandro,
ResponderEliminarLo voy a probar luego te comento.
En realidad aprender c# es una asignatura pendiente, algun dia la voy a cumplir...
Muy buen post te lo digo de nuevo!
Saludos,
Bueno, no tengo problema por agregar una entidad nueva. La cuestión es que para hacerlo pongo una referencia al objeto Employee y otra para Territories y las dos marcadas con la anotación [Key].
ResponderEliminarVisual Stdio me da el error de 'EmployeeTerritories' has no key defined. Define the key for this EntityType.
Es como si no entendiera que es una clave compuesta.
Un saludo y gracias
hola DaNny
ResponderEliminarpero esta tabla EmployeeTerritories es la tipica tabla intermedia de uan relacion muchos a muchos ?
porque si es asi esta no se modela como clase, sino que la defines solo en el nombre al usar el HasMany()
o es que es atabla intermedia contiene algun otro campo?
para definir campo compuestos usarias
HasKey(x => new {x.Employee, x.TerritoryID});
saludos
Leandro como estas mira tus post son muy buenos el entity se ve que ahorra mucho trabajo, estoy empezando a conocer Entity Framework pero estoy muy interesado en el tema no he podido seguir bien un hilo de aprendizaje y en este post me pierdo por que no entiendo como se ejecuta el test si me pudieras dar una mano con una serie de pasos o documentos para aprender y como ejecuto este test
ResponderEliminarhola ksoto
ResponderEliminarimagino estas utilizando alguna version del VS mayor a la Express, si es asi deberias poder ver el proyecto de test y acceder a la ventana
imagen
en la imagen esta la opcion "Test View" con es aopcion listara todos los test, recuerda compilar para que se actualice la lista
despues simplemente es seleccinar uno o todos y usar la opcion de esa ventana para ejecutarlos, aqui lo explica
Cómo: Ejecutar pruebas desde Microsoft Visual Studio
saludos
Hola Leandro, muy buen post. Tengo una consulta, quizás me puedas guiar con algo. El tema es el siguiente: una vez realizado el mapeo de la tabla, posteriormente en la base de datos se cree una tabla con un nombre diferente pero la misma estructura de sus campos y poder utilizar sin realizar cambios en el código fuente, mas bien solo a nivel de sus archivos de esquemas? existe alguna forma de realizar esto, es como especificar el nombre de la tabla de forma dinámica. Gracias por tus comentarios.
ResponderEliminarhola Ismael
ResponderEliminardesde el mapping puedes indicar el nombre de la tabla usando el ToTable()
por ejemplo
public class TerritoryMap : EntityTypeConfiguration
{
public TerritoryMap()
{
ToTable("Terrenos");
HasKey(x => x.TerritoryID);
}
}
como veras defino un nombre que no tiene que ver con el de la clase de la entidad
saludos
hola Leandro, antes que nada un placer y disculpa las molestias, lo que sucede es que deseaba saber si podria ayudarme, soy estudiante de ing. en software y me dejaron como proyecto desarrollar el modelo de runge kutta de cuarto orden pero no se como realizarlo, veo que es posible con matlab y me preguntaba si es posible usar las librerias de matlab para usarlos en c#, es decir para correr las rutinas de matlab en c# 2010 o alguna otra forma usando c#2010, gracias de antemano y un gusto.
ResponderEliminarATTE: Marco Mendoza
P.D. GRACIAS por la atencion en foros/ blogs, me ha servido de mucho sus respuestas a otros usuarios.
hola Marco
ResponderEliminarla verdad no sabria como poder ayudarte ya que no tengo ni idea que es runge kutta
y tampoco he usado matlab integrado con c#
se que hay librerias que puedes referenciar y usar en tu codigo, pero no conozco mucho mas
no preguntaste en los foros de metlab? o quizas ver algun blog que publique como integrarlo con .net, mas que nada que librerias referenciar
saludos
ha, de acuerdo, muchas gracias, verificare en los foros, si encuentro algo y lo resuelvo pasare el tip por aqui.
ResponderEliminarGracias Leandro.
Que pasa si yo solo tengo los codigos(pk) de las entidades que quiero relacionar. A mi entidad 1 le agrego un listado de las unidades relacionadas (entidad 2). Tengo que inicializar todas mi entidades 2 desde la base, algo como:
ResponderEliminarforeach (var e in listaEntidades2)
{
entidad1.entidades2.Add(db.entidades2.SingleOrDefault(x => x.codigo == e));
}
O hay alguna forma de no hacer ese foreach ?
hola Nymph
ResponderEliminarno se si entendi la pregunta
si la entidad2 ya la tienes en la lista podrias ver si se adjunta en el contexto
pero algo que no comentas es si ese listaEntidades2 esta definido con alguna clase que pertenece a EF
porque podrias hacer
foreach (var e in listaEntidades2)
{
context.Entry(e).State = EntityState.Unchanged;
entidad1.entidades2.Add(e);
}
Entity states and SaveChanges
saludos
Gracias por tu respuesta.
ResponderEliminarQuizas no fui tan explicito.
Supongamos que mi accion recibe..
int[] entidades2 (en el view era checkbox solo con el codigo)
Y luego con esos codigo creo objetos entidad2, pero estos solo tienen el codigo, que en resumidas cuentas seria lo unico que yo ocupo para crear una relacion.
Y aqui viene la duda, para mi con los codigos de la entidad 2 me basta, pero no se si EF necesita que yo inicialize cada entidad2 (haciendo el foreach de selects) para agregarlos a la entidad1 o con saber el codigo me basta?
Saludos y gracias.
hola Nymph
ResponderEliminarsi a EF tambien le alcanza con los id, solo que deberias crear la entidad nuevo asignar el id y realizar el attach
Add/Attach and Entity States
podrias definir
EntidadClass entity = new EntidadClass() { Id = valor};
y esa entidad adjuntarla pero marcarla como unchange para que no la vuelva a crear
saludos
Buenisimo Leandro, consulta se puede navegar sobre una propiedad d euna clase q es otra clase mapeada? . pq en mi caso me sale el error
ResponderEliminarLa instancia de ObjectContext se ha eliminado..??? hace falta en el controler al inicio hacer new de todos los repositorie? gracias totales
Leandro buenas tardes , hice todos lso repositorios como publicasates. tenes un ejemplod e un get de una clase con Icoleccition de otra case adentro. no me anda aun. nunca pense que me costaria tanto. con NHibernate tube mas suerte. estoy ahogado ya a punto de largar todo. gracias por al ayuda.
ResponderEliminarhola Ariel
ResponderEliminarpara recuperar una entidad y su colecion asociada solo tienes que usar el Include() indicando la propiedad que quieres cargar de esta forma la query que crear EF ya incluye las relaciones a esa asociacion de navegacion
saludos
hola Leandro , a donde pongo el Include()?
ResponderEliminaren este caso en el Perfil si me lista los usuarios pero en el Usuario No los perfiles, hay que hacer doble map?
aca va un ejemplo de como pueblo pq no anda , igual no ejecuta esa sentencia no el gusta el == no se pq.
using (GigaContext context = new GigaContext())
{
List _l = (List)context.Set().ToList();
foreach (Perfil item in _l)
{
List _u = (List)context.Set().Where( x => x.IdPerfil == item.IdPerfil).ToList();
item.Usuarios = _u;
}
return _l;
}
en el map hay que poner el inlcude??
creo q sigo con NHibernete pq c EF no pego una.
Gracias
te agradezco toda la buena voluntad y increhible dedicacion al los temas. no te jodo mas
ResponderEliminarabandono el estudio de asp mvc sigo con java y hibernate .
gaste tiempo y no anduvo el ORM
gracias totales
hola Ariel
ResponderEliminarcrees que con java y hibernate va a ser mas simple? yo lo dudo, si tienes problemas con .net con java no va a ser mas simple porque el principio no varia tanto
si te gusta hibernate porque no usas NHibernate que es la implementacion para .net
saludos
Hola Leandro no habia leido la pregunta.
ResponderEliminarno digo que sea mas facil. con hibernate trabajo ahce mucho y no em resulto dificl ni al principio. y em funciona. no se si es mejor o peor. me encantaria que me funcione EF. en serio. en este caso me encntaria ver un get all con la clases contenidas. pense q esto hiba a ser mas facil. con toda la mejor.
Leandro ahí pude hacer andar el include
ResponderEliminaraunque todavía no entiendo si mapeamos y ponemos lazy false pq hay q hacer inlcude? ya debería traerlo solo?
ahora la clase q incluyo tambien quiero q incluya una coleccion q tiene dentro
como se hace??
Ejemplo
public override List Menu GetAll()
{
List Menu _lista;
using (GigaContext context = new GigaContext())
{
_lista = (List Menu)context.Menus.Include("MenuItems").ToList();
}
return _lista;
}
quiero que los menuItems tengan adentro , como hago por cada MenuItems.Include("Algo")??
Gracias Totales
hola Ariel
ResponderEliminarrecomendaria veas el video
[Entity Framework] Code First - Cargando Entidades Relacionadas
veras como trabja EF cuando esta lazy activo y como arma la query cuando le indicas que propiedad relacionada vas a utilizar
si ya conoces que hay una propiedad relacionada que vas a trabajar su informacion al definirla en el include() la recupera en una sola operacion, esto es mucho mas optimo que realizar queries individuales por cada dato que consultes
saludos
de donde sacas el : BaseRepository
ResponderEliminaren mi proyecto me marca que no existe el type, estoy poniendo la clase en la carpeta de Model, me gustaria saber si debo poner la clase en otro lado
Buen dia Leandro una pregunta, si se tiene dos tablas una dependiente de la otra como podria hacer una consulta de la dependiente sin que me retorne las propiedades de navegacion.
ResponderEliminares que Tengo esta entidad en EF que es la que quiero hacerle una consulta
public partial class Charity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Charity()
{
this.Registration = new HashSet();
}
public int CharityId { get; set; }
public string CharityName { get; set; }
public string CharityDescription { get; set; }
public string CharityLogo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection Registration { get; set; }
}
pero al devolverla como una lista tipo Charity con este metodo:
MarathonSkills2015Entities context;
public List ListCharity()
{
using (context = new MarathonSkills2015Entities())
{
var charities = (from c in context.Charity
select c).ToList();
return charities;
}
}
me devuelve la columna Registration sin nada pero al colocarlo en un DataGridView me bota un error.
hola
EliminarRespondi en el foro
Consulta en una entidad dependiente EF
saludos
Hola Leandro una pregunta estoy haciendo un proyecto de la facultad y estamos usando mvc 4 con la version 5.0.0.0 del entitty , y no tiene la opcion code first , mas bien estamos usando la opcion EF Disagner desde Base de Datos Y no se como configurar al modelo de la BD que tengo que mapear en mi vista para crear un grupo objetivo con varios clientes
ResponderEliminarhola
EliminarComo que no tiene la opcion de code first? la opcion si esta en EF aunque veo que usan el modelo visual con un edmx
La verdad no entendi que es eso del "grupo objetivo" pero si se trata de una entidad podrias definir la tabla o la clase segun sea que esten en Databse First o Model First. Si generan el modelo en el edmx desde la db podrias generar la tabla y luego actualizar el modelo visual
Hola Leandro, Que pasa si quiero actualizar la lista de Empleados tengo que modificar el método AddEmployees si tu respuesta es si ¿Como?
ResponderEliminarhola
EliminarCuando realizas una asociacion entre entidades realizas operaciones de agregar o remover esta asociacion, pero no existe ninguna operacion de actualizar. Es por eso que tienes el AddEmployees() y RemoveEmployees()
saludos
OK,
EliminarLeandro, he implementado el método Remove pero no ingresa al ForEach para hacer la eliminación
private void dgvModelo_CellContentClick(object sender, DataGridViewCellEventArgs e)
Eliminar{
//Detecta si se ha seleccionado el header de la grilla
if (e.RowIndex == -1)
return;
if(dgvModelo.Columns[e.ColumnIndex].Name == "colSN")
{
//Se toma la fila seleccionada
DataGridViewRow row = dgvModelo.Rows[e.RowIndex];
//Se selecciona la celda del checkbox
DataGridViewCheckBoxCell cellSeleccion = row.Cells["colSN"] as DataGridViewCheckBoxCell;
if(Convert.ToBoolean(cellSeleccion.Value))
{
string mensaje = string.Format("Mensaje. \n\nSe ha seleccionado," +
" \nDescripcion: '{0}'", row.Cells["colDescripcion"].Value);
MetroMessageBox.Show(this, mensaje, strModelo.nameEntity, MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
Proveedor _proveedor = new Proveedor();
_proveedor.ProveedorId = string.IsNullOrEmpty(txtProveedorId.Text)
? 0
: Convert.ToInt32(txtProveedorId.Text);
_proveedor.RazonSocial = txtRazonSocial.Text.Trim();
_proveedor.NroDocumento = txtNroDocumento.Text;
_proveedor.DocumentoIdentidad = ((EnumDocumentoEdentidad)(cboTipoDocumento.SelectedValue));
_proveedor.CategoriaId = Convert.ToInt32(cboCategoria.SelectedValue);
_proveedor.Direccion = txtDireccion.Text;
_proveedor.Fijo = txtFijo.Text;
_proveedor.Celular = txtCelular.Text;
_proveedor.Representante = txtRepresentante.Text;
_proveedor.Email = txtEmail.Text;
List listRowCheck = GetChecked(dgvModelo, "colSN");
_repositoryProveedor.RemoveModelos(_proveedor, listRowCheck);
txtProveedorId.Text = Convert.ToString(_proveedor.ProveedorId);
string mensaje = string.Format("Mensaje. \n\nSe ha quitado la seleccion," +
" \nDescripcion: '{0}'", row.Cells["colDescripcion"].Value);
MetroMessageBox.Show(this, mensaje, strModelo.nameEntity, MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}
Excelente explicacion.
ResponderEliminarPerdon vi que ya hicieron esta pregunta arriba pero me quede con la duda.
Cual es el codigo de esta clase: BaseRepository
o de donde se implementa?
Gracias
Hola Leandro , tienes un ejemplo de como crear una vista (View) en EF codefirst?
ResponderEliminarPlay at Slots.lv Casino! - Dr. Minnesota
ResponderEliminarPlay at 인천광역 출장마사지 Slots.lv Casino! with over 3,000 free 논산 출장안마 slots 출장안마 and video poker games and 70 성남 출장샵 table games, including Blackjack, 서산 출장마사지 Roulette, Craps,