ADO.NET EntityObject Generator: how to get the EntityType’s EntitySet and how to get EntitySet’s EntityTypes?
One of my customers wanted to know how to get all EntityTypes for an EntitySet in his T4 template based on the MS ADO.NET EntityObject Generator one.
So I made a POC for him.
What do I do?
I change two classes included in the template (my changes are in bold):
private class EntitySetObjectSetPropertyWrapper : MetadataItemWrapper
{
public EntitySetObjectSetPropertyWrapper(EntitySet entitySet, WrapperBase wrapper)
: base(entitySet, wrapper)
{
}
public new EntitySet Source { get { return (EntitySet)base.Source; } }
public string ModelName { get { return Source.Name; } }
public string PropertyName { get { return Escape(Source.Name); } }
public string FieldName { get { return "_" + Source.Name; } }
public string TypeName { get { return GetStructuralTypeName(Source.ElementType); } }
public string GetterAccessibility { get { return GetAccessibility(Source, GETTER_ACCESS); } }
public string NewModifier { get { return HasBaseMemberWithMatchingName(typeof(ObjectContext), Source.Name) ? "new " : ""; } }
public IEnumerable<EntityType> GetAllEntityTypes(ItemCollectionWrapper edm)
{
var entityType = Source.ElementType;
yield return entityType;
var entityTypeWrapper = edm.SourceEntities.First(e => e.Source == entityType);
foreach (var subEntityType in entityTypeWrapper.SubEntityTypes(edm))
yield return subEntityType;
}
}
private class EntityTypeWrapper : StructuralTypeWrapper
{
public EntityTypeWrapper(EntityType entity, WrapperBase wrapper)
: base(entity, wrapper)
{
}
public new EntityType Source { get { return (EntityType)base.Source; } }
public string AbstractOption { get { return Source.Abstract ? "abstract " : ""; } }
public bool IsAbstract { get { return Source.Abstract; } }
public string BaseTypeName { get { return Source.BaseType == null ? "EntityObject" : GetStructuralTypeName((StructuralType)Source.BaseType); } }
public string TypeReferenceName { get { return GetStructuralTypeName(Source); } }
public IEnumerable<NavigationPropertyWrapper> NavigationProperties { get { return Source.NavigationProperties.Where(n => n.DeclaringType == Source).Select(n => new NavigationPropertyWrapper(n, this)); } }
public EntitySet GetEntitySet(ItemCollectionWrapper edm)
{
return edm.SourceEntityContainers.SelectMany(c => c.ObjectSetProperties).First(es => es.GetAllEntityTypes(edm).Contains(Source)).Source;
}
public IEnumerable<EntityType> SubEntityTypes(ItemCollectionWrapper edm, bool recursivity = true)
{
return edm.SourceEntities.Where(et => et.AllBaseEntityTypes.Contains(Source)).Select(et => et.Source);
}
public IEnumerable<EntityType> AllBaseEntityTypes
{
get { return GetBaseEntityTypes(Source); }
}
private static IEnumerable<EntityType> GetBaseEntityTypes(EntityType entityType)
{
EntityType baseType;
if (entityType == null || (baseType = (EntityType)entityType.BaseType) == null)
yield break;
yield return baseType;
foreach (var subEntityType in GetBaseEntityTypes(baseType))
yield return subEntityType;
}
}
Note that in your template, you probably don't have the syntax colors.
Then you can use it in the rest of your template as I did in my POC:
/// <summary>
/// <#=set.SummaryComment#>
/// </summary><#=set.GetLongDescriptionComment(_regionIndentLevel)#>
/// <remarks>
/// Entity types:
<# foreach (var entityType in set.GetAllEntityTypes(Edm))
{ #>
/// <#= entityType.Name #>
<# } #>
/// </remarks>
<#=set.NewModifier#><#=set.GetterAccessibility#> ObjectSet<<#=set.TypeName#>> <#=set.PropertyName#>
{
get
{
if ((<#=set.FieldName#> == null))
{
<#=set.FieldName#> = base.CreateObjectSet<<#=set.TypeName#>>("<#=set.ModelName#>");
}
return <#=set.FieldName#>;
}
}
[…]
/// <summary>
/// <#=entity.SummaryComment#>
/// </summary><#=entity.GetLongDescriptionComment(_regionIndentLevel)#>
/// <remarks>EntitySet <#= entity.GetEntitySet(Edm).Name #></remarks>
[EdmEntityTypeAttribute(NamespaceName="<#=entity.ModelNamespace#>", Name="<#=entity.ModelName#>")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
<#
foreach(EntityTypeWrapper subType in Edm.GetAllDirectSubTypes(entity.Source))
{
#>
[KnownTypeAttribute(typeof(<#=subType.TypeReferenceName#>))]
<#
}
#>
<#=entity.TypeAccessibility#> <#=entity.AbstractOption#>partial class <#=entity.ClassName#> : <#=entity.BaseTypeName#>
{
<#
if(!entity.IsAbstract)
{
WriteFactoryMethod(entity.FactoryMethodWrapper);
}
WritePrimitiveTypeProperties(entity, typeof(EntityObject));
WriteComplexTypeProperties(entity, typeof(EntityObject));
#>
I profit by this post to thank Jeff.