jueves, 18 de agosto de 2011

Unir 2 tablas usando linq y claves compuestas

Haciendo una consulta Linq con Entity Framework, he encontrado un problemilla que me ha costado algo de tiempo solucionarlo, y creo que era digno merecedor de una entrada en el blog.

Estaba haciendo una consulta join a 2 tablas con clave compuesta.

var listaCentro = from f in ctx.Facturas
join c in ctx.CentroCoste
on new { f.empresa, f.centroCoste } equals new { c.empresa, c.centro}
select new {c.empresa, c.nombre};

y me aparecía el siguiente error:

“El tipo de una de las expresiones de la cláusula join es incorrecto. No se pudo inferir el tipo en la llamada a 'Join'”

El MSDN me sugería que verificara los tipos del join, comprobando que fueran del mismo tipo las parejas f.empresa, c.empresa y f.centroCoste, c.centro.

Comprobado esto, seguí buscando y me encontré con la siguiente frase:

“La inferencia de tipos en claves compuestas depende de los nombres de las propiedades en las claves y del orden en el que ocurren”

Las claves f.empresa coinciden con c.empresa, pero f.centroCoste no coincide con c.centro, y debían de coincidir.

La solución estaba en poner nombre a las propiedades de las clases anónimas que usamos para las claves compuestas.

var listaCentro = from f in ctx.Facturas
join c in ctx.CentroCoste
on new { emp = f.empresa, centro = f.centroCoste } equals new { emp = c.empresa, centro = c.centro}
select new {c.empresa, c.nombre};

Enlace al artículo MSDN que habla sobrer las claves compuestas:
http://msdn.microsoft.com/es-es/library/bb907099.aspx


11 comentarios:

Anónimo dijo...

muchas gracias tenia el mismo problema y no sabia como resolverlo =) !!

Anónimo dijo...

Muchas gracias, era justo lo que andaba buscando...

Juan Manuel Fenoll dijo...

Me alegro que os sea de utilidad.

Anónimo dijo...

Muy muy útil!!! MUCHAS GRACIAS!!!

Anónimo dijo...

Excelente!!!
De muchísima utilidad

Cabuxa Mapache dijo...

Me has salvado el día, gracias ;)

Desarrollo It dijo...
Este comentario ha sido eliminado por el autor.
Desarrollo It dijo...
Este comentario ha sido eliminado por el autor.
Desarrollo It dijo...

Dn. Juan Manuel Fenoll, mi problema es el siguiente:
No se puede agregar una entidad con una clave que ya está en uso.
esa interrupcion me da cuando hago uso del metodo SubmitChanges() a la Base de Datos(BD) luego de hacer uso del metodo InsertOnSubmit() contenido en un siclo que guarda cada registro en la tabla EmpresaConfiguracion. Como lo muestro en seguida:
foreach (Control c in container.Controls)
{
ec = new Entidad.EmpresaConfiguracion();
ec.EmpresaID = Parametros.General.EmpresaID;
ec.ConfiguracionID = Convert.ToInt32(c.Tag);
db.EmpresaConfiguracion.InsertOnSubmit(ec);
}
db.SubmitChanges();****
en la ultima linea de codigo salta la interrupcion. La tabla con llave compuesta es la siguiente:
CREATE TABLE [wan].[EmpresaConfiguracion](
[EmpresaID] [int] NOT NULL,
[ConfiguracionID] [int] NOT NULL,
[Valor] [nvarchar](1000) NULL,
[Comentario] [varchar](5000) NULL,
CONSTRAINT [PK_EmpresaConfiguracion] PRIMARY KEY CLUSTERED
(
[EmpresaID] ASC,
[ConfiguracionID] ASC
)
segun el script de sql 2012
si hago un insertado desde el sql editor si me permite segun las restricciones obviamente no me permmite en el 3er caso porque se repiten los campos de las llaves primarias(llave compuesta) aqui la prueba:
https://lh3.googleusercontent.com/-r9a6JFldEog/VeTjAVkvTmI/AAAAAAAAAFc/VXZSq_WX11s/w1044-h574-no/LocalServer.png
mi puerba

Anónimo dijo...

Gracias, me sirvio.

José Pozo Oliver dijo...

¡Mil gracias!

Estaba atascado con este problema que me estaba dando la mañana. En mi caso estaba cruzando por dos campos con la peculiaridad de que en una de las tablas podía ser nulo. El compilador indicada que no podía hacer la unión si los tipos no eran idénticos. Lo pude solucionar con algo como:

new { ccc_p = exp.ccc_p, ccc_n = exp.ccc_n, codreg = exp.codreg } equals new { ccc_p = (short?)pat.ccc_p, ccc_n = (int?)pat.ccc_n, codreg = pat.codreg }