3

Using the suggestion provided in GitHub, I was able to generate the EDMX files needed for an ASP.net project. Using a command like:

"%windir%\Microsoft.NET\Framework\v4.0.30319\edmgen.exe" /mode:fullgeneration    /c:"Data Source=%datasourceserver%; Initial Catalog=School; Integrated Security=SSPI"    /project:School /entitycontainer:SchoolEntities /namespace:SchoolModel /language:CSharp

But I don't know how to generate the accompanying edmx.diagram file that gets generated in Visual Studio if we create the EDMX via ADO.Net Data Model addition to existing project.

In the Solution Explorer, the file can be seen in a location like so: enter image description here

The file can also be opened in Visual studio to see the Database structure in the form of a UML diagram like so: enter image description here

Additionally the file generated for this gets shown like so: enter image description here

I read the documentation on how to use edmgen.exe to generate the edmx files as well from the official documentation.

I believe that the documentation to generate the edmx.document file has been missed in the Microsoft documentation and I have been unable to come up with a solution for this by myself. I have been stuck for quite some time on this problem and need help in resolving this.

I have used a similar mechanism to generate files needed in the SQL2LINQ convertor project. Having this capability could help tremendously. Please help me.

Edit 1: I have noticed that the edmx.diagram file has property like so. What I am not sure is if Visual Studio internally uses some other executable to generate the diagram files or if there is an un-documented flag that that can create the diagram files via command line. Please forgive my Edit this information was not avaialable while originally posting the question.

enter image description here

Edit 2: All the steps involved in the process I use:

Step1: Copy my resource files to the folder where I require my edmx and dependency files to be generated.

Note: These files are dummy files and will be generated from the command line command I have pasted in the question.

Step 2: Run the command line command by navigating to the same path.

Step 3: After the command line is run, the connection string collected form the user will help in generating the necessary CSDL, SSDL and MSL files in the same directory. the files are then read and replaced int he edmx files that i have included in the resources folder in the link above.

Step 4: Run The textTransform.bat file to run the texttransform.exe from the Windows SDK path for Texttransform.exe.

Observation: At this stage, 5 of the 6 files are created namely:

  1. .context.tt
  2. .context.cs
  3. .Designer.cs
  4. .tt
  5. .cs

corresponding to the name provided by the user.

But the file .edmx.diagram is missing.

Code that does step 1 through 4:

internal class Globals {
    public static string EDMXworkingDirectory = @"C:\ERachana\EDMX\EDMXFiles\EDMXParts";
    public static bool isEDMXAlreadyGenerated = false;

    public static string Server = "",Database = "", UserName = "",Password = "";
    public static string ProjectName = "", UserDefinedObjectName = "_appdb", TemporaryDirectoryPath="";

    public static string GetSubstringBetweenStrings(string Full, string startMatch, string endMatch) {
        int pFrom = Full.IndexOf(startMatch) + startMatch.Length;
        int pTo = Full.LastIndexOf(endMatch);
        if (pTo > pFrom)
            return Full.Substring(pFrom, pTo - pFrom);
        else
            return "";
    }

    public static void GenerateORMFiles() {
        string workingDirectory = EDMXworkingDirectory;
        if (!isEDMXAlreadyGenerated) {
            // Show Progress Bar here
            try {
                isEDMXAlreadyGenerated = true;
                Directory.CreateDirectory(@"C:\ERachana");
                Directory.CreateDirectory(@"C:\ERachana\EDMX");
                Directory.CreateDirectory(@"C:\ERachana\EDMX\EDMXFiles");
                Directory.CreateDirectory(workingDirectory);

                string CommandToCreateEDMXOnCommandLine = "\"%windir%\\Microsoft.NET\\Framework\\v4.0.30319\\edmgen.exe\" /mode:fullgeneration /c:\"data source = "
                                    + Server + "; initial catalog = "
                                    + Database + "; user id = "
                                    + UserName + "; password = "
                                    + Password + "; MultipleActiveResultSets = True; persist security info = True; App = EntityFramework\" /project:DataModel /entitycontainer:DBContext /namespace:Models /language:CSharp & exit";

                string ResourcesDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Resources\";
                string EDMXFileName = "DataModel.edmx";
                string ContextFileName = "DataModel.Context.tt";
                string TablesFileName = "DataModel.tt";

                string EdmxLocation = workingDirectory + @"\" + EDMXFileName;
                File.Copy(Path.Combine(ResourcesDirectory, EDMXFileName), EdmxLocation, true);
                File.Copy(Path.Combine(ResourcesDirectory, ContextFileName), workingDirectory + @"\" + ContextFileName, true);
                File.Copy(Path.Combine(ResourcesDirectory, TablesFileName), workingDirectory + @"\" + TablesFileName, true);
                using (var process = new Process()) {
                    var startInfo = new ProcessStartInfo {
                        WorkingDirectory = workingDirectory,
                        WindowStyle = ProcessWindowStyle.Minimized,
                        CreateNoWindow = true,
                        RedirectStandardInput = true,
                        UseShellExecute = false,
                        FileName = "cmd.exe",
                        Verb = "runas"
                    };

                    process.StartInfo = startInfo;
                    process.Start();
                    process.StandardInput.WriteLine(CommandToCreateEDMXOnCommandLine);
                    process.WaitForExit();
                    process.Close();
                    process.Dispose();
                }
                string text = File.ReadAllText(EdmxLocation);

                string c = "";
                c = parseSCMDLFiles(workingDirectory + @"\DataModel.ssdl", "Schema");
                text = text.Replace("###StorageModelsSchema", c);

                c = parseSCMDLFiles(workingDirectory + @"\DataModel.csdl", "Schema");
                text = text.Replace("###ConceptualModelsSchema", c);

                c = parseSCMDLFiles(workingDirectory + @"\DataModel.msl", "Mapping");
                text = text.Replace("###Mappings", c);

                File.WriteAllText(EdmxLocation, text);

                string[] fileToBeDeleted = Directory.GetFiles(workingDirectory);
                foreach (string filePath in fileToBeDeleted) {
                    if (filePath.Contains("DataModel.ObjectLayer.cs") || filePath.Contains("DataModel.Views.cs")) {
                        File.Delete(filePath);
                    } else {
                        if (filePath.ToLower().Contains(".edmx") || filePath.ToLower().Contains(".tt") || filePath.ToLower().Contains(".cs"))
                            continue;
                        File.Delete(filePath);
                    }
                }
                string location = @"C:\ERachana\EDMX";
                string TransformFileName = "transform_all.bat";
                File.Copy(Path.Combine(ResourcesDirectory, TransformFileName), location + @"\" + TransformFileName, true);
                string batFileCommand = "/C " + location + @"\" + TransformFileName;

                using (var process = new Process()) {
                    var startInfo = new ProcessStartInfo() {
                        WorkingDirectory = location,
                        WindowStyle = ProcessWindowStyle.Minimized,
                        CreateNoWindow = true,
                        UseShellExecute = false,
                        FileName = @"cmd.exe",
                        Verb = "runas",
                        Arguments = batFileCommand
                    };

                    process.StartInfo = startInfo;
                    process.Start();
                    process.WaitForExit();
                    process.Close();
                    process.Dispose();
                }
            } catch {
                MessageBox.Show("Only Projects with MSSQL may be converted to Web Projects");
            } finally {
                // Close Progressbar here
            }
        }
    }

    public static string parseSCMDLFiles(string EDMXDirectoryFile, string tag) {
        List<string> lines = File.ReadLines(EDMXDirectoryFile).ToList();
        string content = "";
        bool flagEnable = false;
        foreach (string line in lines) {
            if (line.Contains("</" + tag + ">"))
                flagEnable = false;
            if (flagEnable == true)
                content += line + Environment.NewLine;
            if (line.Contains("<" + tag))
                flagEnable = true;
        }
        return content;
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • What would you use this for? At runtime, the diagram file isn't used. At design time, it is, but a diagram is generated automatically if needed. –  Jan 20 '18 at 09:23
  • Hi @hvd. In ASP.net project I need this diagram to show a visualization of database tables. The output of my tool, will need to be customized by other people who are working on the same project and it will grately help if they can see the visualization as they develop. – Ganesh Kamath - 'Code Frenzy' Jan 20 '18 at 09:36
  • Hi @hvd. Is there a way to independantly generate the diagram at design time if we delete the diagram file manually? – Ganesh Kamath - 'Code Frenzy' Jan 20 '18 at 10:28

1 Answers1

2

Short Answer

To make the edmx designer show the diagrams, you can use either of the following options:

  • Having <Designers></Designers> tag in edmx file.

  • Having .edmx.designer file with following contents and child of .edmx file:

    <?xml version="1.0" encoding="utf-8"?>
    <edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
      <edmx:Designer>
        <edmx:Diagrams>
    
        </edmx:Diagrams>
      </edmx:Designer>
    </edmx:Edmx>
    

Long Answer

EdmGen.exe will not generate edmx for you, but it generates all data that you need to create an edmx file yourself. You can simply create edmx file by mixing those csdl, ssdl and msl.

Also about the diagram file, you should know edmx.diagram file is not necessary. When you create the edmx file, with empty <Diagrams></Diagrams> tag, the first time that you open the edmx file in designer, Visual Studio will create the content for the tag for you. Then if for any reason you like to have ot in separate file, you can simply right click on design surface of the edmx and choose Move Diagrams to Separate File.

You can follow the following steps to create an edmx file manually (or by code) yourself:

1- Run EdmGen

"%windir%\Microsoft.NET\Framework\v4.0.30319\edmgen.exe" /mode:fullgeneration  /c:"Data Source=SERVERNAME; Initial Catalog=DATABASENAME;Integrated Security=SSPI" /project:PROJECT /entitycontainer:CONTAINER /namespace:NAMESPACE /language:CSharp /targetversion:4.5

2- Create an edmx file with following contents.

Please note that the edmx content which I used in this post, is based on /targetversion:4.5 switch.

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
    $SSDL$
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
    $CSDL$
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
    $MSL$
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
    <Connection>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
      </DesignerInfoPropertySet>
    </Connection>
    <Options>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="ValidateOnBuild" Value="true" />
        <DesignerProperty Name="EnablePluralization" Value="true" />
        <DesignerProperty Name="IncludeForeignKeysInModel" Value="true" />
        <DesignerProperty Name="UseLegacyProvider" Value="false" />
        <DesignerProperty Name="CodeGenerationStrategy" Value="None" />
      </DesignerInfoPropertySet>
    </Options>
    <!-- Diagram content (shape and connector positions) -->
    <Diagrams></Diagrams>
  </Designer>
</edmx:Edmx>

3- Replace the placeholders which you have in edmx with content of the following files (without <?xml version="1.0" encoding="utf-8"?>):

  • $SSDL$ should be replaced with content of the ssdl file.
  • $CSDL$ should be replaced with content of the csdl file.
  • $MSL$ should be replaced with content of the msl file.

Note

.edmx.designer is optional and it's enough to have an <Diagrams></Diagrams> tag in edmx like what I shared above, then the first time that you open Visual Studio, the diagram will be created for you automatically. Also for any reason if you like to have diagram i a separate file, you can simply create an empty diagram file, which will be filled by VS at the first time that you open edmx:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <edmx:Designer>
    <edmx:Diagrams>

    </edmx:Diagrams>
  </edmx:Designer>
</edmx:Edmx>
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Hi @Reza Aghaei, Thank you for looking into the problem. I believe I am already doing the step 1, 2 and 3 in the code. I wanted to know if you know some way to fill the `` tag above with the appropriate content and if there is a way to generate the.edms.Diagram file. the difference is that i am using `###StorageModelsSchema` instead of `$SSDL$` to replace the respective sections – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 07:32
  • Hi @GaneshKamath-'CodeFrenzy' You don't need to fill the diagram section. It's just some UI information and will be filled automatically by VS the first time that you open the file in VS. – Reza Aghaei Jan 25 '18 at 08:43
  • Hi @Reza Aghaei, For some reason, VS does not generate this in the Project that I generate. I think there is some way to calculate the PointX, PointY co-ordinates that are displayed int he xml format shown in the question above. – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 14:33
  • I don't say VS will generate `edmx.diagram`. It will generate the contents for ``. `edmx.diagram` is not necessary. What's the usage of `.edmx.diagram` for you. It's enough to open edmx in Visual Studio to be able to see the diagram, without having any `edmx.diagram`. – Reza Aghaei Jan 25 '18 at 14:39
  • In fact if you right click in design surface of `edmx` and click `Move Diagram to separate files` then it will generate `.edmx.diagram` file and moves the content of `` to that file. – Reza Aghaei Jan 25 '18 at 14:45
  • okay, let me try one more time and add more details to the question in case that solves my problem. At the end of the day, I want to generate the .edmx.diagram via comman line and not via Visual Studio – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 14:48
  • I should emphasis that `edmx.designer` is not necessary and you can see the diagram, without having `edmx.designer`, just by having an empty `` tag in `edmx` file. It's the important point. – Reza Aghaei Jan 25 '18 at 14:50
  • Hi @Reza Aghaei, I know that it is optional. That is exactly what has kept our project going for the past 4 months. But There is a lot of push to make the EDMX part complete and have all features, as if when developed from scratch through visual studio. That is why I am asking this on Stackoverflow. Trying your solution with empty design tags. – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 15:23
  • I see, but Visual Studio also creates the diagrams at the first time that you open edmx. – Reza Aghaei Jan 25 '18 at 15:30
  • The short answer is, you should have either of `` empty tag in edmx or the content which I shared as `edmx.diagram` file content. – Reza Aghaei Jan 25 '18 at 15:37
  • Thanks for sharing the schema @Reza Aghaei, somehow it is not creating the file even after adding it directly to the project and adding the tag `/targetversion:4.5` – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 16:18
  • You're welcome. For me using VS 2017 (version 15.5.4) it works properly. I shared the exact steps what I'm using. – Reza Aghaei Jan 25 '18 at 16:20
  • The importance of `/targetversion:4.5` is just because of the schema versions and urls. – Reza Aghaei Jan 25 '18 at 16:23
  • Oh, I am working on VS 2015. Sorry forgot to mention. – Ganesh Kamath - 'Code Frenzy' Jan 25 '18 at 16:32
  • While the version of VS may be important, but before making any assumption, make sure you are following the exact steps correctly. – Reza Aghaei Jan 25 '18 at 16:42