zoukankan      html  css  js  c++  java
  • Entity Framework 从数据库生成模型丢失数据库文档不完美解决方案

    Entity Framework 从数据库导入模型时,导入工具生成的EDMX文件是不带有数据库建表时填写的 MS_Description 属性的,今天急用,东拼西凑了几句代码。

    <#@ assembly name="System.Core" #>
    <#@ assembly name="System.Data" #>
    <#@ assembly name="System.Xml" #>
    <#@ assembly name="System.Xml.Linq" #>
    <#@ assembly name="System.Data.Entity" #>
    <#@ assembly name="System.Data.Entity.Design" #>
    <#@ assembly name="$(DevEnvDir)Microsoft.Data.Entity.Design.DatabaseGeneration.dll"#>
    <#@ assembly name="EnvDTE" #>
    <#@ assembly name="System.Configuration" #>
    <#@ assembly name="System.Windows.Forms" #>
    <#@ import namespace="System" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="System.IO" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Xml.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Text.RegularExpressions" #>
    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.Common" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ import namespace="System.Data.EntityClient" #>
    <#@ import namespace="System.Data.Entity.Design" #>
    <#@ import namespace="System.Data.Metadata.Edm" #>
    <#@ import namespace="System.Diagnostics" #>
    <#@ import namespace="System.Globalization" #>
    <#@ import namespace="System.Configuration" #>
    <#@ import namespace="System.Runtime.Remoting.Messaging" #>
    <#@ import namespace="System.Windows.Forms" #>
    <#@ import namespace="Microsoft.Data.Entity.Design.DatabaseGeneration" #>
    <#@ include file="EF.Utility.CS.ttinclude"#>
    <#@ template language="C#" debug="true" hostspecific="true" #>
    <#@ output extension = ".txt" #><#
    
    //修改为要修正的edmx文件
    var inputFile = @"Models.edmx";
    
    
    
    
    
    
    
    
    
    var loader = new MetadataLoader(this);
    var region = new CodeRegion(this);
    
    var ItemCollection = loader.CreateEdmItemCollection(inputFile);
    EntityContainer container = ItemCollection.GetItems<EntityContainer>().FirstOrDefault();
    
    //项目路径
    string CurrProjectPath =  GetProjectPath();
    
    //连接名称=容器名称
    string CurrConnectionStringName = container==null?string.Empty:container.Name ;
    string CurrConnectionString = string.Empty;
    string CurrProviderName= string.Empty;
    
    CurrConnectionString = GetConnectionString(ref CurrConnectionStringName,out CurrProviderName);
    
    //EntityClientConnectionString转SqlClientConnectionString
    if(CurrConnectionString.StartsWith("meta"))
    {
        EntityConnectionStringBuilder scsb= new EntityConnectionStringBuilder(CurrConnectionString);
        CurrConnectionString = scsb.ProviderConnectionString;
        CurrProviderName = scsb.Provider;
    }
    
    
    using(FixEDMXDoc fixEDMXDoc = new FixEDMXDoc(CurrConnectionString,CurrProjectPath + "\\" + inputFile,CurrProjectPath + "\\" + inputFile))
    {
    	fixEDMXDoc.CreateDocumentation();
    }
    #><#+
    public EnvDTE.Project GetCurrentProject()  {
    
        IServiceProvider _ServiceProvider = (IServiceProvider)Host;
        if (_ServiceProvider == null)
            throw new Exception("Host property returned unexpected value (null)");
    	
        EnvDTE.DTE dte = (EnvDTE.DTE)_ServiceProvider.GetService(typeof(EnvDTE.DTE));
        if (dte == null)
            throw new Exception("Unable to retrieve EnvDTE.DTE");
    	
        Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
        if (activeSolutionProjects == null)
            throw new Exception("DTE.ActiveSolutionProjects returned null");
    	
        EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
        if (dteProject == null)
            throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
    	
        return dteProject;
    
    }
    
    private string GetProjectPath()
    {
        EnvDTE.Project project = GetCurrentProject();
        System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
        return info.Directory.FullName;
    }
    
    private string GetConfigPath()
    {
        EnvDTE.Project project = GetCurrentProject();
        foreach (EnvDTE.ProjectItem item in project.ProjectItems)
        {
            // if it is the app.config file, then open it up
            if (item.Name.Equals("App.config",StringComparison.InvariantCultureIgnoreCase) || item.Name.Equals("Web.config",StringComparison.InvariantCultureIgnoreCase))
    			return GetProjectPath() + "\\" + item.Name;
        }
        return String.Empty;
    }
    string GetConnectionString(ref string connectionStringName, out string providerName)
    {
        var _CurrentProject = GetCurrentProject();
    
    	providerName=null;
        
        string result="";
        ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
        configFile.ExeConfigFilename = GetConfigPath();
    
        if (string.IsNullOrEmpty(configFile.ExeConfigFilename))
            throw new ArgumentNullException("The project does not contain App.config or Web.config file.");
        
        
        var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
        var connSection=config.ConnectionStrings;
    
        //if the connectionString is empty - which is the defauls
        //look for count-1 - this is the last connection string
        //and takes into account AppServices and LocalSqlServer
        if(string.IsNullOrEmpty(connectionStringName))
        {
            if(connSection.ConnectionStrings.Count>1)
            {
    			connectionStringName = connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].Name;
                result=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ConnectionString;
                providerName=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ProviderName;
            }            
        }
        else
        {
            try
            {
                result=connSection.ConnectionStrings[connectionStringName].ConnectionString;
                providerName=connSection.ConnectionStrings[connectionStringName].ProviderName;
            }
            catch
            {
                result="There is no connection string name called '"+connectionStringName+"'";
            }
        }
    	if (String.IsNullOrEmpty(providerName))
    		providerName="System.Data.SqlClient";
        return result;
    }
    
    //Copy From http://eftsqldocgenerator.codeplex.com/
    class FixEDMXDoc : IDisposable
    {
        public String ConnectionString { get; set; }
        public String InputFileName { get; set; }
        public String OutputFileName { get; set; }
    
        private SqlConnection _connection;
    
    
        public FixEDMXDoc(String connectionString, String inputFileName, String outputFileName)
        {
            this.ConnectionString = connectionString;
            this.InputFileName = inputFileName;
            this.OutputFileName = outputFileName;
    
            
            this._connection = new SqlConnection(connectionString);
            this._connection.Open();
        }
        public void Dispose()
        {
            this._connection.Dispose();
        }
    
        public void CreateDocumentation()
        {
    
            XDocument doc = XDocument.Load(this.InputFileName);
            IEnumerable<XElement> entityTypeElements = doc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}EntityType");
    		
            foreach (XElement entityTypeElement in entityTypeElements)
            {
                String tableName = entityTypeElement.Attribute("Name").Value;
                IEnumerable<XElement> propertyElements = entityTypeElement.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Property");
    
    
    
                this.AddNodeDocumentation(entityTypeElement, GetTableDocumentation(tableName));
    
                foreach (XElement propertyElement in propertyElements)
                {
                    String columnName = propertyElement.Attribute("Name").Value;
                    this.AddNodeDocumentation(propertyElement, GetColumnDocumentation(tableName, columnName));
                }
            }
    
            Console.WriteLine("Writing result to {0}", this.OutputFileName);
            if (File.Exists(this.OutputFileName))
                File.Delete(this.OutputFileName);
            doc.Save(this.OutputFileName);
        }
        private void AddNodeDocumentation(XElement element, String documentation)
        {
            if (String.IsNullOrEmpty(documentation))
                return;
            element.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation").Remove();
    
            element.AddFirst(new XElement("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation", new XElement("{http://schemas.microsoft.com/ado/2008/09/edm}Summary", documentation)));
        }
        private String GetTableDocumentation(String tableName)
        {
            using (SqlCommand command = new SqlCommand(@" SELECT [value] 
                                                          FROM fn_listextendedproperty (
                                                                'MS_Description', 
                                                                'schema', 'dbo', 
                                                                'table',  @TableName, 
                                                                null, null)", this._connection))
            {
    
                command.Parameters.AddWithValue("TableName", tableName);
    
                return command.ExecuteScalar() as String;
            }
        }
        private String GetColumnDocumentation(String tableName, String columnName)
        {
            using (SqlCommand command = new SqlCommand(@"SELECT [value] 
                                                         FROM fn_listextendedproperty (
                                                                'MS_Description', 
                                                                'schema', 'dbo', 
                                                                'table', @TableName, 
                                                                'column', @columnName)", this._connection))
            {
    
                command.Parameters.AddWithValue("TableName", tableName);
                command.Parameters.AddWithValue("ColumnName", columnName);
    
                return command.ExecuteScalar() as String;
            }
        }
    }
    #>
    

      把上面的代码保存为[.tt]类型的文件,并加入项目,修改 [var inputFile = @"Models.edmx";]这句的 Models.edmx为要添加文档的edmx文件,然后保存。

    实体模型更改后,要重新写入文档,这时在 这个[.tt]文件上点右键,选择“运行自定义工具”。

  • 相关阅读:
    Docker--Dockerfile引用及指令集的功能用法
    Docker容器的启动与停止
    Docker--删除容器实例和镜像
    CentOS安装Docker
    Docker运行简单的Demo
    VMware安装的Windows10下Docker的安装
    ASP.NET Core使用EPPlus操作Excel
    只有程序员才懂的幽默(转)
    iOS 简单代理(delegate)实现
    iOS设计模式——委托(delegate)
  • 原文地址:https://www.cnblogs.com/binsys/p/2321525.html
Copyright © 2011-2022 走看看