4

I need to modify the T4 template POCO.tt to retrieve the database schema from the EDMX file. I can see the schema stored in an EntitySet tag in the XML. However I cannot find the schema anywhere when using an EntitySet object.

Anyone know where I would find the database schema?

Thanks

37Stars
  • 2,489
  • 20
  • 23

5 Answers5

7

UPDATE I wrote up my findings on this in a blog post:

http://www.ninjanye.co.uk/2011/06/getting-schema-information-from-edmx.html

http://jnye.co/Posts/3/getting-schema-information-from-an-edmx-file-with-poco

I came across this same problem myself. First you need to retrieve the EntityContainer from the Storage Model Content (edmx:StorageModels) section of the edmx file

At the top of the tt template (after the MetadataLoader is instantiated and the inputFile is declared) add the following code to get the Storage Model Content EntityContainer

StoreItemCollection sic;
loader.TryCreateStoreItemCollection(inputFile, out sic);
EntityContainer sicEntityContainer = sic.GetItems<EntityContainer>().First();

Then from within the foreach (var entity in ItemCollection.GetItems...) loop you can get the current schema with the following

EntitySet eset = sicEntityContainer.GetEntitySetByName(code.Escape(entity), true);
string schemaName = eset.MetadataProperties["Schema"].Value.ToString();

Note: You may have to repeat the get schema code for ComplexType properties lower down in the tt template

NinjaNye
  • 7,046
  • 1
  • 32
  • 46
  • Thanks. I haven't worked on this set of code for sometime, but still, this information is helpful. – 37Stars May 02 '11 at 15:47
  • `code.Escape(entity)` should just be `entity.Name` because Escape will add `@` if the name happens to be a keyword. Also, this isn't foolproof because the name you're passing to `GetEntitySetByName` comes from the edmx:ConceptualModels section, while you're actually trying to look up a name under edmx:StorageModels. These aren't necessarily the same, and are mapped under the "C-S" mapping section. Unfortunately there is no easy API to read this section (see http://social.msdn.microsoft.com/Forums/en-US/d019e830-8d3c-4e66-8aec-14aa675caae0/dynamically-obtain-mapping-info). – nmclean Jul 18 '13 at 16:16
1

I'm working with EF6 and wanted to add a summary comment to the classes being generated by the t4 template. After hacking around for a while, I managed to do it by loading the EDMX file and using XPath to find what I needed.

var xmlContent = XDocument.Load(textTransform.Host.ResolvePath(inputFile));
var edmxNavigator = xmlContent.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(edmxNavigator.NameTable);
nsMgr.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2009/11/edmx");
nsMgr.AddNamespace("store", "http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator");
nsMgr.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/11/edm/ssdl");
nsMgr.AddNamespace("cs", "http://schemas.microsoft.com/ado/2009/11/mapping/cs");
//This is the loop that came with the default template
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);

    var mappingAttribute = edmxNavigator.SelectSingleNode("/edmx:Edmx/edmx:Runtime/edmx:Mappings/cs:Mapping/cs:EntityContainerMapping/cs:EntitySetMapping/cs:EntityTypeMapping[@TypeName=\"" + entity.FullName + "\"]/cs:MappingFragment/@StoreEntitySet", nsMgr);
    var entitySet = edmxNavigator.SelectSingleNode("/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/ssdl:EntityContainer/ssdl:EntitySet[@Name=\"" + mappingAttribute.Value + "\"]", nsMgr);
    var actualTableName  = (entitySet.SelectSingleNode("@Table") ?? entitySet.SelectSingleNode("@Name")).Value;
    var actualSchemaName = (entitySet.SelectSingleNode("@Schema", nsMgr) ?? entitySet.SelectSingleNode("@store:Schema", nsMgr)).Value;  

#>

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>

/// <summary>
/// Database Object: <#=actualSchemaName#>.<#=actualTableName#>
/// </summary>
<#=codeStringGenerator.EntityClassOpening(entity)#>
K0D4
  • 2,373
  • 1
  • 27
  • 26
  • For this to work you also need to include `<#@ import namespace="System.Xml.XPath"#>` at the top of your file – donatasj87 Mar 24 '22 at 13:58
  • If you are still using EDMX, I highly suggest moving to EF6 or EFCore if you can swing it. The EF Core Power Tools VISX extension really remove a lot of the need for doing stuff like this. – K0D4 Mar 31 '22 at 21:08
1

I think I misunderstood your question the first time. Have you examined the edmx schema for any clues?

According to this link: http://msdn.microsoft.com/en-us/library/cc982042.aspx

The schema for applications that target the .NET Framework version 4 is defined in the Microsoft.Data.Entity.Design.Edmx_2.xsd file. The schema for applications that target the .NET Framework version 3.5 SP1 is defined in the Microsoft.Data.Entity.Design.Edmx_1.xsd file.

Those are in %VS100COMNTOOLS%\..\..\Xml\Schemas\ for VS 2010, and %VS90COMNTOOLS%\..\..\Xml\Schemas\ (the 3.5 only) for VS 2008

Peter T. LaComb Jr.
  • 2,935
  • 2
  • 29
  • 44
0

See http://brewdawg.github.io/Tiraggo.Edmx/ you can install it via NuGet within Visual Studio and it serves up ALL of the metadata from your EDMX files that Microsoft hides from you, very simple, works great. You want access to all that low level storage information like your property SQL types, the schema, it's all there. You can even use the Sample Windows.Forms app in the github repo to set a breakpoint and examine the data.

0

Facing this issue a few weeks ago. As a result create Xslt transformation of EDMX to XSD. https://wash-inside-out.blogspot.com/2022/12/edmx-file-to-xsd-with-xslt.html

Igor Azarny
  • 124
  • 1
  • 3
  • I do not see how this answers the question at the top of this page, but it should. Please [edit] according to [answer] or delete the answer. Otherwise it risks being flagged as "not an answer" and being deleted. – Yunnosch Dec 06 '22 at 21:11
  • Maybe the part "As a result create ..." is what confuses me most and prevents me from understanding how this is an answer. Do you mean "The result of my researches is that you should create ...." ? In that case please provide details. If you mean "The result is that I created ..." then this is a link-only answer, i.e. the solution itself is not here and not even summarised here. Such a link-only answer is not considered an answer on StackOverflow and risks being flagged and deleted. – Yunnosch Dec 07 '22 at 08:46