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]文件上点右键,选择“运行自定义工具”。