started getting framework first ejemplo data code entity-framework-4.1 ef-code-first

entity framework 4.1 - getting - Primero, el código de Entity Framework. Encontrar clave principal



entity framework code first data annotations (5)

Al igual que el usuario rashleighp, también quería una variante de la respuesta del usuario Ladislav Mrnka que solo necesita saber el tipo en tiempo de ejecución en lugar de tener que saber el tipo en tiempo de compilación. También como usuario rashleighp, la solución del usuario S''pht''Kr no funcionó para mí, pero su solución funcionó. A continuación, contribuyo a esta conversación proporcionando una versión más simple de su respuesta que funcionó para mí. Sin embargo, acabo de enterarme de la solución por usuario anjdreas y esa es la que voy a utilizar.

// variable "type" is a System.Type passed in as a method parameter ((IObjectContextAdapter)context) .ObjectContext .MetadataWorkspace .GetItem<EntityType>(type.FullName, DataSpace.OSpace) .KeyProperties .Select(p => p.Name);

¿Cómo puedo encontrar qué propiedad de una clase es la clave principal de Entity Framework Code First POCO?

Tenga en cuenta que la coincidencia de cadenas para Id / class name + "Id" es una mala opción. Debe haber alguna forma de extraer la convención utilizada por Entity Framework y obtener de manera confiable la propiedad clave.

Gracias por adelantado.


En EF 6.1 hay un método de extensión Db() que lo hace más fácil.

Ejemplo:

public static IEnumerable<string> GetPrimaryKeyPropertyNames(DbContext db, Type entityType) { return db.Db(entityType).Pks.Select(x => x.PropertyName); }


En caso de que ayude a alguien, necesitaba poder hacer esto sin saber el tipo de antemano (por lo que no podría hacer CreateObjectSet<YourEntity>() porque no conocía YourEntity ), así que pude adaptar @ La solución de Ladislav en lo siguiente:

// variable "type" is a System.Type passed in as a method parameter ObjectContext objectContext = ((IObjectContextAdapter)this.context).ObjectContext; IEnumerable<string> retval = (IEnumerable<string>)objectContext.MetadataWorkspace .GetType(type.Name, type.Namespace, System.Data.Entity.Core.Metadata.Edm.DataSpace.CSpace) .MetadataProperties .Where(mp => mp.Name == "KeyMembers") .First() .Value;

Parece algo extraño que MetadataWorkspace.GetType requiera cadenas del nombre de tipo y el espacio de nombres, en lugar de un System.Type, pero eso es lo mejor que pude encontrar.


Puede solicitar metadatos de mapeo para obtener los nombres de las propiedades clave (puede haber más de uno):

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; ObjectSet<YourEntity> set = objectContext.CreateObjectSet<YourEntity>(); IEnumerable<string> keyNames = set.EntitySet.ElementType .KeyMembers .Select(k => k.Name);

Una vez que tenga los nombres de las teclas, puede usar la reflexión para acceder a sus valores.

Como puede ver, el enfoque vuelve a la API de ObjectContext porque DbContext API es solo para escenarios simples en los que no se molesta con detalles como la asignación de metadatos.


Tuve un problema con los dos enfoques anteriores debido a la herencia Table Per Type. Mi versión de trabajo (basada en la solución de @S''pht''Kr pero usando DataSpace.OSpace no DataSpace.CSpace por este motivo) está a continuación:

protected IEnumerable<string> GetKeyPropertyNames() { var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter) this.Context).ObjectContext; return GetKeyPropertyNames(typeof (TEntity), objectContext.MetadataWorkspace); } private static IEnumerable<string> GetKeyPropertyNames(Type type, MetadataWorkspace workspace) { EdmType edmType; if (workspace.TryGetType(type.Name, type.Namespace, DataSpace.OSpace, out edmType)) { return edmType.MetadataProperties.Where(mp => mp.Name == "KeyMembers") .SelectMany(mp => mp.Value as ReadOnlyMetadataCollection<EdmMember>) .OfType<EdmProperty>().Select(edmProperty => edmProperty.Name); } return null; }