In the process of writing an import system for importing data into a database modeled by EF, I needed to be able to grab table/column information from the model. Following is a method I wrote for doing that (it's more difficult than it seems).
First, here is the class I'm populating in the main method. Of course, you could add properties to this as necessary:
Update: There is a bug in the code below. It's impossible to edit the (pasted in) HTML now. the select after "var foreignKeyNames" below should be:
select ( p.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One ) ?
( (AssociationType)p.RelationshipType ).ReferentialConstraints[0].FromProperties[0].Name :
( (AssociationType)p.RelationshipType ).ReferentialConstraints[0].ToProperties[0].Name );
public
class
EntityTypeInfo
{
public string EntityName { get; set; }
public string PropertyName { get; set; }
public Type EntityType { get; set; }
///
/// Identity, Computed columns
///
public bool StoreGenerated { get; set; }
public bool IsForeignKey { get; set; }
}
Now the main method along with a helper method (see update above):
- /// <summary>
- /// For the given table/entity list, build a list of type info.
- /// </summary>
- public static List<EntityTypeInfo> SimplePropertiesFrom( ObjectContext context, List<string> tables )
- {
- var result = new List<EntityTypeInfo>();
-
- /// We have to draw from two different spaces to get all the info we need.
- var conceptualMetadata = context.MetadataWorkspace.GetItems( DataSpace.CSpace );
- /// context.MetadataWorkspace.GetItems() for storage space only works if queries have already run which we can't ensure here.
- var storageMetadata = ( (EntityConnection)context.Connection ).GetMetadataWorkspace().GetItems( DataSpace.SSpace );
-
- var query = from c in conceptualMetadata
- join s in storageMetadata on
- c.BuiltInTypeKind == BuiltInTypeKind.EntityType ? ( (EntityType)c ).Name : "X" // If the item isn't an EntityType, we don't want a join, so just make these 2 values different
- equals
- s.BuiltInTypeKind == BuiltInTypeKind.EntityType ? ( (EntityType)s ).Name : ""
- where c.BuiltInTypeKind == BuiltInTypeKind.EntityType
- select new { conceptual = c as EntityType, storage = s as EntityType };
- query.ToList().ForEach( field =>
- {
- if ( tables.Contains( field.conceptual.Name ) )
- {
- var foreignKeyProps = ( from p in field.conceptual.NavigationProperties
- where p.RelationshipType is AssociationType && ((AssociationType)p.RelationshipType).IsForeignKey
- select ( ( AssociationType )p.RelationshipType ).ReferentialConstraints[0].FromProperties[0].Name );
- foreach ( var p in field.conceptual.Properties )
- {
- result.Add( new EntityTypeInfo
- {
- EntityName = field.conceptual.Name,
- PropertyName = p.Name,
- EntityType = ( (PrimitiveType)p.TypeUsage.EdmType ).ClrEquivalentType,
- StoreGenerated = IsStoreGenerated( p, field.storage ),
- IsForeignKey = foreignKeyProps.Contains( p.Name )
- } );
- }
- }
- } );
- return result;
- }
-
- private static bool IsStoreGenerated( EdmProperty conceptualEntityProperty, EntityType storageEntityType )
- {
- EdmMember storageProperty;
- storageEntityType.Members.TryGetValue( conceptualEntityProperty.Name, true, out storageProperty );
- if ( storageProperty == null )
- {
- return false;
- }
- else
- {
- Facet f;
- if ( storageProperty.TypeUsage.Facets.TryGetValue( "StoreGeneratedPattern", false, out f) )
- {
- return ( ( (StoreGeneratedPattern)f.Value ) == StoreGeneratedPattern.Identity ) || ( ( (StoreGeneratedPattern)f.Value ) == StoreGeneratedPattern.Computed );
- }
- else
- {
- /// If it's not store generated, the above property won't be there (StoreGeneratedPattern.None is never referenced).
- return false;
- }
- }
- }