5

Tengo un problema desafiante en el que me gustaría utilizar la reflexión en mi mapeo de Entity Framework para encontrar todas las claves foráneas que hacen referencia a una tabla, y quiero los nombres de las columnas que son las claves foráneasEntity Framework - Reflexión sobre claves externas y relaciones/asociaciones

De acuerdo con another post on SO, puedo encontrar fácilmente las propiedades de navegación en una tabla a través de la reflexión. Pero esto no me da el nombre de la propiedad o columna que contiene el valor de la clave externa.

La razón por la que intento hacer esto es porque tengo una gran cantidad de tablas (casi 40) que hacen referencia a una tabla de elementos. Digamos que un usuario ingresa un nuevo valor en la tabla de elementos llamada "Andew" y luego un administrador se da cuenta de que en realidad es solo un error tipográfico para el elemento "Andrew" ya existente. Ahora quiero encontrar todas las referencias a "Andew" y cambiar esas referencias a "Andrew". Preferiría hacer esto de manera eficiente, por lo que usar las propiedades de navegación inversa sería demasiado lento ya que tienes que cargar los valores antes de modificarlos. Lo que me gustaría hacer es poder reflejar una lista de tablas y columnas, luego emitir comandos de actualización directamente a la base de datos. Se vería algo como esto:

var command = String.Format("UPDATE [{0}] SET [{1}] = {{1}} WHERE [{1}] = {{0}}; ", fk.FromTableName, fk.FromColumnName); 
dataContext.ExecuteStoreCommand(command, new Object[] { oldID, newID }); 

En LINQ a SQL esto era en realidad bastante fácil ... 20 líneas de reflexión en el código generado automáticamente LINQ y yo estaba hecho, pero nos cambiaron a EF hace poco y me no puede encontrar los nombres de las columnas de clave externa a través de EF.

Un ejemplo simplificado de lo que estoy buscando: si tengo un objeto llamado Employee con una propiedad de navegación llamada Manager y una clave foránea de ManagerID, entonces quiero saber que Manager es mi propiedad de navegación y el almacenamiento subyacente es la propiedad ManagerID. Quiero hacer esto estrictamente a través de la reflexión o los metadatos para poder construir una consulta dinámica a partir de él.

+1

tienes un voto negativo, así que supongo que no soy el único que tiene problemas para entender lo que buscas. ¿Puedes hacer 'employee.managerId' o' employee.manager.id'? tienes que saber cuál es la convención, tu DBA no puede simplemente cambiar la base de datos sin que afecte tu proyecto de otras formas. – Eonasdan

+0

@Eonasdan - gracias. Me preguntaba por qué estaba degradado. Reescribí completamente para que sea mucho más claro. Desafortunadamente ahora es mucho más largo, y estaba tratando de mantenerlo corto. – pbarranis

Respuesta

1

vez que haya utilizado las ideas en la cuestión vinculada al llegar al EntityType que le interesa, tenga en cuenta que EntityType hereda de EntityTypeBase, que tiene una propiedad KeyMembers que es una colección de todos los EdmMembers que participan en el la clave de la entidad.

Cada EdmMember tiene un Name que será la cadena "ManagerID" que usted busca.

+1

Eso es una buena idea, pero necesito obtener el nombre de la clave externa en el objeto actual, no la clave del objeto extraño. Es la diferencia entre myObject.ManagerID y myObject.Manager.ID. No utilizamos la convención de Manager.ManagerID, utilizamos Manager.ID, por lo que las columnas se nombran de manera diferente en cada extremo. – pbarranis

1

Solo para ahorrar tiempo, quiero descartar esto es no la respuesta correcta, pero puede hacer lo que estoy pidiendo a través de vistas del sistema en SQL. Lo he intentado y funciona, pero me molesta poder obtener estos datos tan fácilmente a través de LINQ a SQL, pero no puedo encontrarlo en EF. Si no hay otra alternativa, tendré que usar la siguiente solución. (EF Pero tiene que tener estos datos internamente en alguna parte ... sólo quiero acceso a ella.)

select K.name as RelationshipName, T1.name as FromTable, C1.name as FromColumn, T2.name as ToTable, C2.name as ToColumn 
from sys.foreign_keys as K 
join sys.foreign_key_columns as C on K.object_id = C.constraint_object_id 
join sys.columns as C1 on K.parent_object_id = C1.object_id 
join sys.tables as T1 on K.parent_object_id = T1.object_id 
join sys.columns as C2 on K.referenced_object_id = C2.object_id 
join sys.tables as T2 on K.referenced_object_id = T2.object_id 
where C1.column_id = C.parent_column_id 
and C2.column_id = C.referenced_column_id 
and T2.Name = 'Employee' 
order by T1.Name, C1.Name 

suerte de publicar esta respuesta incorrecta es al menos útil para alguien que no sea yo ... (también, lo digo , esta solución necesita mucho más código para trabajar con PK de varias columnas; las mías son todas de columna única).

Cuestiones relacionadas