How to programmatically generate Entity Framework Model DbFirst based on DbContext

I am looking for a way to programmatically generate an Entity Framework model Database First for a given database based on DbContext.

Now, I have been experimenting with the class System.Data.Entity.Design.EntityCodeGenerator, but only seems to generate them based on ObjectContext.

http://msdn.microsoft.com/en-us/library/system.data.entity.design.entitycodegenerator(v=vs.110).aspx

Here I found info on how to use it: http://blogs.msdn.com/b/adonet/archive/2008/06/20/edm-tools-options-part-1-of-4.aspx

But still only ObjectContext based model are generated.

UPDATE: I need to do this from inside a Visual Studio extension (so it has Visual Studio as sandbox).

Upvotes: 1

Views: 1072

Answers (1)

Ok, I found a way, documenting it here in case someone else has the same issue: instead of generating the code for the model backend (Model.Designer.cs for example) with System.Data.Entity.Design.EntityCodeGenerator, now I am just adding the .edmx to the Visual Studio project, setting some properties, and Visual Studio takes care of everything:

private void AddToProject( string edmxPath)
    {
      string edmxCodePath;
      ProjectItem pi = _vsProj.Project.ProjectItems.AddFromFile(edmxPath);
      // this little magic replaces having to use System.Data.Entity.Design.EntityCodeGenerator
      pi.Properties.Item("ItemType").Value = "EntityDeploy";
      pi.Properties.Item("CustomTool").Value = "EntityModelCodeGenerator";
      if( efVersion == BaseWizard<BaseWizardForm, BaseCodeGeneratorStrategy>.ENTITY_FRAMEWORK_VERSION_6)
      {
        // For EF6 we use DbContext instead of ObjectContext based context.
        _vsProj.DTE.SuppressUI = true;
        EnvDTE80.Solution2 sol = (EnvDTE80.Solution2)_vsProj.DTE.Solution;
        string itemPath = "";
        if( this.Language == LanguageGenerator.CSharp )
        {
          itemPath = sol.GetProjectItemTemplate("DbCtxCSEF6", "CSharp" );
        } else {
          itemPath = sol.GetProjectItemTemplate("DbCtxVBEF6", "VisualBasic");
        }
        pi.ProjectItems.AddFromTemplate(itemPath, this._modelName);
        // update $edmxInputFile$
        string path = Path.GetDirectoryName(edmxPath);
        string templateName = Path.Combine(path, _modelName + ".tt");
        string contents = File.ReadAllText(templateName);
        File.WriteAllText(templateName, contents.Replace("$edmxInputFile$", _modelName + ".edmx"));
        templateName = Path.Combine(path, _modelName + ".Context.tt");
        contents = File.ReadAllText(templateName);
        File.WriteAllText(templateName, contents.Replace("$edmxInputFile$", _modelName + ".edmx"));
      }
    }

Explanation: the method receives the path to the .edmx file generated, if EF version is 6, the template "DbCtxCSEF6" is instantied (which is always installed with VS2013), then is just a matter of replacing the $edmxInputFile$ with the edmx filename; Visual Studio will automatically add the .tt templates and generate the backend code.

For more details in the context, see the code for MySql.Data.VisualStudio.Wizards.EntityFrameworkGenerator class from MySql for Visual Studio 1.2.1 or above.

Installers and source code (its open sourced) available at:

http://dev.mysql.com/downloads/windows/visualstudio/

Upvotes: 1

Related Questions