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