解决EF没有生成字段和表说明

      项目中使用了EF框架,使用的是Database-First方式,因为数据库已经存在,所以采用Database-First方式,ef生成实体类的时候,发现微软没有自动生成表字段和表说明,在网上找了些资料,由于都不太全,倒腾了近2个小时,所以根据网上的帖子为基础,写得更详细一点,让初学者更容易明白和少走弯路。网上也有一些自动生成的软件,可以自动生成,但是更新数据库需要重新生成,有点麻烦,所有根据T4模板解决

第一步:

      我们需要有GetSummery.ttinclude文件,

  1 <#@ template language="C#v3.5" hostspecific="True" #>
  2 <#@ assembly name="EnvDTE" #>
  3 <#@ assembly name="System.Data" #>
  4 <#@ assembly name="System.Xml" #>
  5 <#@ assembly name="System.Configuration" #>
  6 <#@ assembly name="System.Windows.Forms" #>
  7 <#@ import namespace="System.Collections.Generic" #>
  8 <#@ import namespace="System.Data" #>
  9 <#@ import namespace="System.Data.SqlClient" #>
 10 <#@ import namespace="System.Data.Common" #>
 11 <#@ import namespace="System.Diagnostics" #>
 12 <#@ import namespace="System.Globalization" #>
 13 <#@ import namespace="System.IO" #>
 14 <#@ import namespace="System.Linq" #>
 15 <#@ import namespace="System.Text" #>
 16 <#@ import namespace="System.Text.RegularExpressions" #>
 17 <#@ import namespace="System.Configuration" #>
 18 <#@ import namespace="System.Windows.Forms" #>
 19 <#+
 20 
 21 string ConnectionStringName = "ConnStr";
 22 string Namespace = "";
 23 string RepoName = "";
 24 string ClassPrefix = "";
 25 string ClassSuffix = "";
 26 string SchemaName = null;
 27 bool IncludeViews = false;
 28 bool GenerateOperations = false;
 29 bool GenerateCommon = true;
 30 bool GeneratePocos = true;
 31 bool TrackModifiedColumns = false;
 32 
 33 
 34 static Regex rxCleanUp = new Regex(@"[^wd_]", RegexOptions.Compiled);
 35 
 36 static Func<string, string> CleanUp = (str) =>
 37 {
 38     str = rxCleanUp.Replace(str, "_");
 39     if (char.IsDigit(str[0])) str = "_" + str;
 40     
 41     return str;
 42 };
 43 
 44 
 45 
 46 string GetConnectionString(ref string connectionStringName, out string providerName)
 47 {
 48     var _CurrentProject = GetCurrentProject();
 49 
 50     providerName=null;
 51     
 52     string result="";
 53     ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
 54     configFile.ExeConfigFilename = GetConfigPath();
 55 
 56     if (string.IsNullOrEmpty(configFile.ExeConfigFilename))
 57         throw new ArgumentNullException("The project does not contain App.config or Web.config file.");
 58     
 59     
 60     var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
 61     var connSection=config.ConnectionStrings;
 62 
 63     //if the connectionString is empty - which is the defauls
 64     //look for count-1 - this is the last connection string
 65     //and takes into account AppServices and LocalSqlServer
 66     if(string.IsNullOrEmpty(connectionStringName))
 67     {
 68         if(connSection.ConnectionStrings.Count>1)
 69         {
 70             connectionStringName = connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].Name;
 71             result=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ConnectionString;
 72             providerName=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ProviderName;
 73         }            
 74     }
 75     else
 76     {
 77         try
 78         {
 79             result=connSection.ConnectionStrings[connectionStringName].ConnectionString;
 80             providerName=connSection.ConnectionStrings[connectionStringName].ProviderName;
 81         }
 82         catch
 83         {
 84             result="There is no connection string name called '"+connectionStringName+"'";
 85         }
 86     }
 87 
 88 //    if (String.IsNullOrEmpty(providerName))
 89 //        providerName="System.Data.SqlClient";
 90     
 91     return result;
 92 }
 93 
 94 string _connectionString="";
 95 string _providerName="";
 96 
 97 void InitConnectionString()
 98 {
 99     if(String.IsNullOrEmpty(_connectionString))
100     {
101         _connectionString=GetConnectionString(ref ConnectionStringName, out _providerName);
102 
103         if(_connectionString.Contains("|DataDirectory|"))
104         {
105             //have to replace it
106             string dataFilePath=GetDataDirectory();
107             _connectionString=_connectionString.Replace("|DataDirectory|",dataFilePath);
108         }    
109     }
110 }
111 
112 public string ConnectionString
113 {
114     get 
115     {
116         InitConnectionString();
117         return _connectionString;
118     }
119 }
120 
121 public string ProviderName
122 {
123     get 
124     {
125         InitConnectionString();
126         return _providerName;
127     }
128 }
129 
130 public EnvDTE.Project GetCurrentProject()  {
131 
132     IServiceProvider _ServiceProvider = (IServiceProvider)Host;
133     if (_ServiceProvider == null)
134         throw new Exception("Host property returned unexpected value (null)");
135     
136     EnvDTE.DTE dte = (EnvDTE.DTE)_ServiceProvider.GetService(typeof(EnvDTE.DTE));
137     if (dte == null)
138         throw new Exception("Unable to retrieve EnvDTE.DTE");
139     
140     Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
141     if (activeSolutionProjects == null)
142         throw new Exception("DTE.ActiveSolutionProjects returned null");
143     
144     EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
145     if (dteProject == null)
146         throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
147     
148     return dteProject;
149 
150 }
151 
152 private string GetProjectPath()
153 {
154     EnvDTE.Project project = GetCurrentProject();
155     System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
156     return info.Directory.FullName;
157 }
158 
159 private string GetConfigPath()
160 {
161     EnvDTE.Project project = GetCurrentProject();
162     foreach (EnvDTE.ProjectItem item in project.ProjectItems)
163     {
164         // if it is the app.config file, then open it up
165         if (item.Name.Equals("App.config",StringComparison.InvariantCultureIgnoreCase) || item.Name.Equals("Web.config",StringComparison.InvariantCultureIgnoreCase))
166             return GetProjectPath() + "\" + item.Name;
167     }
168     return String.Empty;
169 }
170 
171 public string GetDataDirectory()
172 {
173     EnvDTE.Project project=GetCurrentProject();
174     return System.IO.Path.GetDirectoryName(project.FileName)+"\App_Data\";
175 }
176 
177 static string zap_password(string connectionString)
178 {
179     var rx = new Regex("password=.*;", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.IgnoreCase);
180     return rx.Replace(connectionString, "password=**zapped**;");
181 }
182 
183 //得到列说明
184 string getColumnSummery(string tablename,string columnname)
185 {
186     InitConnectionString();
187     DbProviderFactory _factory;
188     
189    _factory = DbProviderFactories.GetFactory(ProviderName);
190     
191     using(var conn=_factory.CreateConnection())
192     {
193         conn.ConnectionString=ConnectionString;         
194         conn.Open();
195         
196             
197         //string sql=@"SELECT TOP 1 ex.value FROM sys.columns c LEFT OUTER JOIN sys.extended_properties ex ON ex.major_id = c.object_id AND ex.minor_id = c.column_id AND ex.name = 'MS_Description' left outer join systypes t on c.system_type_id=t.xtype WHERE OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0 ";
198         string sql=@"SELECT TOP 1 ex.value FROM sys.columns c LEFT OUTER JOIN sys.extended_properties ex ON ex.major_id = c.object_id AND ex.minor_id = c.column_id AND ex.name = 'MS_Description' left outer join systypes t on c.system_type_id=t.xtype WHERE OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0 AND OBJECT_NAME(c.object_id)=@tablename AND c.name=@columname ";
199         
200         using (var cmd=_factory.CreateCommand())
201         {
202             cmd.Connection=conn;
203             cmd.CommandText=sql;
204 
205             var p = cmd.CreateParameter();
206             p.ParameterName = "@tablename";
207             p.Value=tablename;
208             cmd.Parameters.Add(p);
209 
210              p = cmd.CreateParameter();
211             p.ParameterName = "@columname";
212             p.Value=columnname;
213             cmd.Parameters.Add(p);
214 
215             var result=cmd.ExecuteScalar();
216 
217             conn.Close();
218 
219             if(result!=null)
220                 return result.ToString();    
221             else
222                 return ProviderName;
223         }        
224           
225         return "";
226     
227     }
228          
229 }
230 
231 
232 
233 
234 //得到表说明备注
235 string getTableSummery(string tablename)
236 {
237     InitConnectionString();
238     DbProviderFactory _factory;
239     
240    _factory = DbProviderFactories.GetFactory(ProviderName);
241     
242     using(var conn=_factory.CreateConnection())
243     {
244         conn.ConnectionString=ConnectionString;         
245         conn.Open();
246         
247             
248         //string sql=@"SELECT TOP 1 ex.value FROM sys.columns c LEFT OUTER JOIN sys.extended_properties ex ON ex.major_id = c.object_id AND ex.minor_id = c.column_id AND ex.name = 'MS_Description' left outer join systypes t on c.system_type_id=t.xtype WHERE OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0 ";
249         string sql=@"SELECT TOP 1 TableSumary FROM (select c.Name AS TableName,isnull(f.[value],'') AS TableSumary from  sys.columns a left join sys.types b on a.user_type_id=b.user_type_id inner join  sys.objects c on a.object_id=c.object_id and c.Type='U' left join  syscomments d on a.default_object_id=d.ID left join sys.extended_properties e on e.major_id=c.object_id and e.minor_id=a.Column_id and e.class=1 left join  sys.extended_properties f on f.major_id=c.object_id and f.minor_id=0 and f.class=1) AS Mytb WHERE TableName=@tablename ";
250         
251         using (var cmd=_factory.CreateCommand())
252         {
253             cmd.Connection=conn;
254             cmd.CommandText=sql;
255 
256             var p = cmd.CreateParameter();
257             p.ParameterName = "@tablename";
258             p.Value=tablename;
259             cmd.Parameters.Add(p);
260 
261             var result=cmd.ExecuteScalar();
262 
263             conn.Close();
264 
265             if(result!=null)
266                 return result.ToString();    
267             else
268                 return ProviderName;
269         }        
270           
271         return "";
272     
273     }
274          
275 }
276 
277 
278 
279 
280 
281 /// <summary>
282 /// Summary for the Inflector class
283 /// </summary>
284 public static class Inflector {
285     private static readonly List<InflectorRule> _plurals = new List<InflectorRule>();
286     private static readonly List<InflectorRule> _singulars = new List<InflectorRule>();
287     private static readonly List<string> _uncountables = new List<string>();
288 
289     /// <summary>
290     /// Initializes the <see cref="Inflector"/> class.
291     /// </summary>
292     static Inflector() {
293         AddPluralRule("$", "s");
294         AddPluralRule("s$", "s");
295         AddPluralRule("(ax|test)is$", "$1es");
296         AddPluralRule("(octop|vir)us$", "$1i");
297         AddPluralRule("(alias|status)$", "$1es");
298         AddPluralRule("(bu)s$", "$1ses");
299         AddPluralRule("(buffal|tomat)o$", "$1oes");
300         AddPluralRule("([ti])um$", "$1a");
301         AddPluralRule("sis$", "ses");
302         AddPluralRule("(?:([^f])fe|([lr])f)$", "$1$2ves");
303         AddPluralRule("(hive)$", "$1s");
304         AddPluralRule("([^aeiouy]|qu)y$", "$1ies");
305         AddPluralRule("(x|ch|ss|sh)$", "$1es");
306         AddPluralRule("(matr|vert|ind)ix|ex$", "$1ices");
307         AddPluralRule("([m|l])ouse$", "$1ice");
308         AddPluralRule("^(ox)$", "$1en");
309         AddPluralRule("(quiz)$", "$1zes");
310 
311         AddSingularRule("s$", String.Empty);
312         AddSingularRule("ss$", "ss");
313         AddSingularRule("(n)ews$", "$1ews");
314         AddSingularRule("([ti])a$", "$1um");
315         AddSingularRule("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis");
316         AddSingularRule("(^analy)ses$", "$1sis");
317         AddSingularRule("([^f])ves$", "$1fe");
318         AddSingularRule("(hive)s$", "$1");
319         AddSingularRule("(tive)s$", "$1");
320         AddSingularRule("([lr])ves$", "$1f");
321         AddSingularRule("([^aeiouy]|qu)ies$", "$1y");
322         AddSingularRule("(s)eries$", "$1eries");
323         AddSingularRule("(m)ovies$", "$1ovie");
324         AddSingularRule("(x|ch|ss|sh)es$", "$1");
325         AddSingularRule("([m|l])ice$", "$1ouse");
326         AddSingularRule("(bus)es$", "$1");
327         AddSingularRule("(o)es$", "$1");
328         AddSingularRule("(shoe)s$", "$1");
329         AddSingularRule("(cris|ax|test)es$", "$1is");
330         AddSingularRule("(octop|vir)i$", "$1us");
331         AddSingularRule("(alias|status)$", "$1");
332         AddSingularRule("(alias|status)es$", "$1");
333         AddSingularRule("^(ox)en", "$1");
334         AddSingularRule("(vert|ind)ices$", "$1ex");
335         AddSingularRule("(matr)ices$", "$1ix");
336         AddSingularRule("(quiz)zes$", "$1");
337 
338         AddIrregularRule("person", "people");
339         AddIrregularRule("man", "men");
340         AddIrregularRule("child", "children");
341         AddIrregularRule("sex", "sexes");
342         AddIrregularRule("tax", "taxes");
343         AddIrregularRule("move", "moves");
344 
345         AddUnknownCountRule("equipment");
346         AddUnknownCountRule("information");
347         AddUnknownCountRule("rice");
348         AddUnknownCountRule("money");
349         AddUnknownCountRule("species");
350         AddUnknownCountRule("series");
351         AddUnknownCountRule("fish");
352         AddUnknownCountRule("sheep");
353     }
354 
355     /// <summary>
356     /// Adds the irregular rule.
357     /// </summary>
358     /// <param name="singular">The singular.</param>
359     /// <param name="plural">The plural.</param>
360     private static void AddIrregularRule(string singular, string plural) {
361         AddPluralRule(String.Concat("(", singular[0], ")", singular.Substring(1), "$"), String.Concat("$1", plural.Substring(1)));
362         AddSingularRule(String.Concat("(", plural[0], ")", plural.Substring(1), "$"), String.Concat("$1", singular.Substring(1)));
363     }
364 
365     /// <summary>
366     /// Adds the unknown count rule.
367     /// </summary>
368     /// <param name="word">The word.</param>
369     private static void AddUnknownCountRule(string word) {
370         _uncountables.Add(word.ToLower());
371     }
372 
373     /// <summary>
374     /// Adds the plural rule.
375     /// </summary>
376     /// <param name="rule">The rule.</param>
377     /// <param name="replacement">The replacement.</param>
378     private static void AddPluralRule(string rule, string replacement) {
379         _plurals.Add(new InflectorRule(rule, replacement));
380     }
381 
382     /// <summary>
383     /// Adds the singular rule.
384     /// </summary>
385     /// <param name="rule">The rule.</param>
386     /// <param name="replacement">The replacement.</param>
387     private static void AddSingularRule(string rule, string replacement) {
388         _singulars.Add(new InflectorRule(rule, replacement));
389     }
390 
391     /// <summary>
392     /// Makes the plural.
393     /// </summary>
394     /// <param name="word">The word.</param>
395     /// <returns></returns>
396     public static string MakePlural(string word) {
397         return ApplyRules(_plurals, word);
398     }
399 
400     /// <summary>
401     /// Makes the singular.
402     /// </summary>
403     /// <param name="word">The word.</param>
404     /// <returns></returns>
405     public static string MakeSingular(string word) {
406         return ApplyRules(_singulars, word);
407     }
408 
409     /// <summary>
410     /// Applies the rules.
411     /// </summary>
412     /// <param name="rules">The rules.</param>
413     /// <param name="word">The word.</param>
414     /// <returns></returns>
415     private static string ApplyRules(IList<InflectorRule> rules, string word) {
416         string result = word;
417         if (!_uncountables.Contains(word.ToLower())) {
418             for (int i = rules.Count - 1; i >= 0; i--) {
419                 string currentPass = rules[i].Apply(word);
420                 if (currentPass != null) {
421                     result = currentPass;
422                     break;
423                 }
424             }
425         }
426         return result;
427     }
428 
429     /// <summary>
430     /// Converts the string to title case.
431     /// </summary>
432     /// <param name="word">The word.</param>
433     /// <returns></returns>
434     public static string ToTitleCase(string word) {
435         return Regex.Replace(ToHumanCase(AddUnderscores(word)), @"([a-z])",
436             delegate(Match match) { return match.Captures[0].Value.ToUpper(); });
437     }
438 
439     /// <summary>
440     /// Converts the string to human case.
441     /// </summary>
442     /// <param name="lowercaseAndUnderscoredWord">The lowercase and underscored word.</param>
443     /// <returns></returns>
444     public static string ToHumanCase(string lowercaseAndUnderscoredWord) {
445         return MakeInitialCaps(Regex.Replace(lowercaseAndUnderscoredWord, @"_", " "));
446     }
447 
448 
449     /// <summary>
450     /// Adds the underscores.
451     /// </summary>
452     /// <param name="pascalCasedWord">The pascal cased word.</param>
453     /// <returns></returns>
454     public static string AddUnderscores(string pascalCasedWord) {
455         return Regex.Replace(Regex.Replace(Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-zd])([A-Z])", "$1_$2"), @"[-s]", "_").ToLower();
456     }
457 
458     /// <summary>
459     /// Makes the initial caps.
460     /// </summary>
461     /// <param name="word">The word.</param>
462     /// <returns></returns>
463     public static string MakeInitialCaps(string word) {
464         return String.Concat(word.Substring(0, 1).ToUpper(), word.Substring(1).ToLower());
465     }
466 
467     /// <summary>
468     /// Makes the initial lower case.
469     /// </summary>
470     /// <param name="word">The word.</param>
471     /// <returns></returns>
472     public static string MakeInitialLowerCase(string word) {
473         return String.Concat(word.Substring(0, 1).ToLower(), word.Substring(1));
474     }
475 
476 
477     /// <summary>
478     /// Determine whether the passed string is numeric, by attempting to parse it to a double
479     /// </summary>
480     /// <param name="str">The string to evaluated for numeric conversion</param>
481     /// <returns>
482     ///     <c>true</c> if the string can be converted to a number; otherwise, <c>false</c>.
483     /// </returns>
484     public static bool IsStringNumeric(string str) {
485         double result;
486         return (double.TryParse(str, NumberStyles.Float, NumberFormatInfo.CurrentInfo, out result));
487     }
488 
489     /// <summary>
490     /// Adds the ordinal suffix.
491     /// </summary>
492     /// <param name="number">The number.</param>
493     /// <returns></returns>
494     public static string AddOrdinalSuffix(string number) {
495         if (IsStringNumeric(number)) {
496             int n = int.Parse(number);
497             int nMod100 = n % 100;
498 
499             if (nMod100 >= 11 && nMod100 <= 13)
500                 return String.Concat(number, "th");
501 
502             switch (n % 10) {
503                 case 1:
504                     return String.Concat(number, "st");
505                 case 2:
506                     return String.Concat(number, "nd");
507                 case 3:
508                     return String.Concat(number, "rd");
509                 default:
510                     return String.Concat(number, "th");
511             }
512         }
513         return number;
514     }
515 
516     /// <summary>
517     /// Converts the underscores to dashes.
518     /// </summary>
519     /// <param name="underscoredWord">The underscored word.</param>
520     /// <returns></returns>
521     public static string ConvertUnderscoresToDashes(string underscoredWord) {
522         return underscoredWord.Replace('_', '-');
523     }
524 
525 
526     #region Nested type: InflectorRule
527 
528     /// <summary>
529     /// Summary for the InflectorRule class
530     /// </summary>
531     private class InflectorRule {
532         /// <summary>
533         /// 
534         /// </summary>
535         public readonly Regex regex;
536 
537         /// <summary>
538         /// 
539         /// </summary>
540         public readonly string replacement;
541 
542         /// <summary>
543         /// Initializes a new instance of the <see cref="InflectorRule"/> class.
544         /// </summary>
545         /// <param name="regexPattern">The regex pattern.</param>
546         /// <param name="replacementText">The replacement text.</param>
547         public InflectorRule(string regexPattern, string replacementText) {
548             regex = new Regex(regexPattern, RegexOptions.IgnoreCase);
549             replacement = replacementText;
550         }
551 
552         /// <summary>
553         /// Applies the specified word.
554         /// </summary>
555         /// <param name="word">The word.</param>
556         /// <returns></returns>
557         public string Apply(string word) {
558             if (!regex.IsMatch(word))
559                 return null;
560 
561             string replace = regex.Replace(word, replacement);
562             if (word == word.ToUpper())
563                 replace = replace.ToUpper();
564 
565             return replace;
566         }
567     }
568 
569     #endregion
570 }
571 
572 #>
GetSummery.ttinclude

,GetSummery.ttinclude是模板文件,为了实现EF框架添加数据库自动生成实体注释。

第二步:

     把GetSummery.ttinclude文件放到Model1.edmx同一级目录,当然也可以放到其他路径,为了方便放到同一级目录。

第三步:

     打开GetSummery.ttinclude文件,修改GetSummery.ttinclude连接数据库的字符串改为"ConnStr",prioviderName属性必须要有哦。

第四步:

     打开EF项目文件所在的tt文件

第五步:

        在tt头部添加 <#@ include file="GetSummery.ttinclude" #>

     

第六步:

    加载自定义TT文件用来获取数据库表备注和字段备注说明

    在TT文件里搜索:<#=codeStringGenerator.UsingDirectives(inHeader: false)#>

    把代码添加<#=codeStringGenerator.UsingDirectives(inHeader: false)#>到下面 

/// <summary>
/// <#= getTableSummery(code.Escape(entity)) #>
/// </summary>

第七步:

      第二次搜索:<#=codeStringGenerator.Property(edmProperty)#>, 在它上方插入代码:

/// <summary>
/// <#= getColumnSummery(code.Escape(entity),code.Escape(edmProperty)) #>
/// </summary>

第八步:

     保存TT文件,它会自动更新数据库里的各个实体

    效果图如下  :

   

最后附上完整的代码:

<#@ template language="C#" debug="false" hostspecific="true"#> 
 <#@ include file="GetSummery.ttinclude" #>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>

 <#

const string inputFile = @"OADBModel.edmx";
var textTransform = DynamicTextTransformation.Create(this);
var code = new CodeGenerationTools(this);
var ef = new MetadataTools(this);
var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
var    fileManager = EntityFrameworkTemplateFileManager.Create(this);
var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);

if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
{
    return string.Empty;
}

WriteHeader(codeStringGenerator, fileManager);
string summary=string.Empty;
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);
    if(entity.Documentation !=null && entity.Documentation.Summary!=null)
       summary=entity.Documentation.Summary;
     else
        summary=entity.Name;
#>

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
/// <summary>
/// <#= getTableSummery(code.Escape(entity)) #>
/// </summary>
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
<#
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
    var complexProperties = typeMapper.GetComplexProperties(entity);

    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
    {
#>
    public <#=code.Escape(entity)#>()
    {
<#
        foreach (var edmProperty in propertiesWithDefaultValues)
        {
#>
        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
        }

        foreach (var navigationProperty in collectionNavigationProperties)
        {
#>
        this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
        }

        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>
    }

<#
    }

    var simpleProperties = typeMapper.GetSimpleProperties(entity);
    if (simpleProperties.Any())
    {
        foreach (var edmProperty in simpleProperties)
        {
        if (edmProperty.Documentation != null && edmProperty.Documentation.Summary != null)
          {
           summary=edmProperty.Documentation.Summary;
          }
         else
          {
           summary="";
          }
#>
    /// <summary>
    /// <#= getColumnSummery(code.Escape(entity),code.Escape(edmProperty)) #>
    /// </summary>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }

    if (complexProperties.Any())
    {
#>

<#
        foreach(var complexProperty in complexProperties)
        {
#>
    <#=codeStringGenerator.Property(complexProperty)#>
<#
        }
    }

    var navigationProperties = typeMapper.GetNavigationProperties(entity);
    if (navigationProperties.Any())
    {
#>

<#
        foreach (var navigationProperty in navigationProperties)
        {
         if(navigationProperty.Documentation != null &&navigationProperty.Documentation.Summary != null)
                     {
                     summary=navigationProperty.Documentation.Summary;
                     }
                     else
                     {
                     summary="";
                     }
#>
    /// <summary>
    /// <#=summary#>
    /// </summary>
    <#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#
        }
    }
#>
}
<#
    EndNamespace(code);
}

foreach (var complex in typeMapper.GetItemsToGenerate<ComplexType>(itemCollection))
{
    fileManager.StartNewFile(complex.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
{
<#
    var complexProperties = typeMapper.GetComplexProperties(complex);
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);

    if (propertiesWithDefaultValues.Any() || complexProperties.Any())
    {
#>
    public <#=code.Escape(complex)#>()
    {
<#
        foreach (var edmProperty in propertiesWithDefaultValues)
        {
#>
        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
        }

        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>
    }

<#
    }

    var simpleProperties = typeMapper.GetSimpleProperties(complex);
    if (simpleProperties.Any())
    {
        foreach(var edmProperty in simpleProperties)
        {
#>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }

    if (complexProperties.Any())
    {
#>

<#
        foreach(var edmProperty in complexProperties)
        {
#>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }
#>
}
<#
    EndNamespace(code);
}

foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection))
{
    fileManager.StartNewFile(enumType.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
<#
    if (typeMapper.EnumIsFlags(enumType))
    {
#>
[Flags]
<#
    }
#>
<#=codeStringGenerator.EnumOpening(enumType)#>
{
<#
    var foundOne = false;
    
    foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType))
    {
        foundOne = true;
#>
    <#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>,
<#
    }

    if (foundOne)
    {
        this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1);
    }
#>
}
<#
    EndNamespace(code);
}

fileManager.Process();

#>
<#+

public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager)
{
    fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
// <#=GetResourceString("Template_GeneratedCodeCommentLine1")#>
//
// <#=GetResourceString("Template_GeneratedCodeCommentLine2")#>
// <#=GetResourceString("Template_GeneratedCodeCommentLine3")#>
// </auto-generated>
//------------------------------------------------------------------------------
<#=codeStringGenerator.UsingDirectives(inHeader: true)#>
<#+
    fileManager.EndBlock();
}

public void BeginNamespace(CodeGenerationTools code)
{
    var codeNamespace = code.VsNamespaceSuggestion();
    if (!String.IsNullOrEmpty(codeNamespace))
    {
#>
namespace <#=code.EscapeNamespace(codeNamespace)#>
{
<#+
        PushIndent("    ");
    }
}

public void EndNamespace(CodeGenerationTools code)
{
    if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion()))
    {
        PopIndent();
#>
}
<#+
    }
}

public const string TemplateId = "CSharp_DbContext_Types_EF5";

public class CodeStringGenerator
{
    private readonly CodeGenerationTools _code;
    private readonly TypeMapper _typeMapper;
    private readonly MetadataTools _ef;

    public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
    {
        ArgumentNotNull(code, "code");
        ArgumentNotNull(typeMapper, "typeMapper");
        ArgumentNotNull(ef, "ef");

        _code = code;
        _typeMapper = typeMapper;
        _ef = ef;
    }

    public string Property(EdmProperty edmProperty)
    {
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1} {2} {{ {3}get; {4}set; }}",
            Accessibility.ForProperty(edmProperty),
            _typeMapper.GetTypeName(edmProperty.TypeUsage),
            _code.Escape(edmProperty),
            _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
            _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
    }

    public string NavigationProperty(NavigationProperty navigationProperty)
    {
        var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1} {2} {{ {3}get; {4}set; }}",
            AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
            navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
            _code.Escape(navigationProperty),
            _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
            _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
    }
    
    public string AccessibilityAndVirtual(string accessibility)
    {
        return accessibility + (accessibility != "private" ? " virtual" : "");
    }
    
    public string EntityClassOpening(EntityType entity)
    {
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1}partial class {2}{3}",
            Accessibility.ForType(entity),
            _code.SpaceAfter(_code.AbstractOption(entity)),
            _code.Escape(entity),
            _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
    }
    
    public string EnumOpening(SimpleType enumType)
    {
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} enum {1} : {2}",
            Accessibility.ForType(enumType),
            _code.Escape(enumType),
            _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
        }
    
    public void WriteFunctionParameters(EdmFunction edmFunction, Action<string, string, string, string> writeParameter)
    {
        var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
        foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
        {
            var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
            var notNullInit = "new ObjectParameter("" + parameter.EsqlParameterName + "", " + parameter.FunctionParameterName + ")";
            var nullInit = "new ObjectParameter("" + parameter.EsqlParameterName + "", typeof(" + parameter.RawClrTypeName + "))";
            writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
        }
    }
    
    public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
    {
        var parameters = _typeMapper.GetParameters(edmFunction);
        
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} IQueryable<{1}> {2}({3})",
            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
            _code.Escape(edmFunction),
            string.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray()));
    }
    
    public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
    {
        var parameters = _typeMapper.GetParameters(edmFunction);
        
        return string.Format(
            CultureInfo.InvariantCulture,
            "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>("[{1}].[{2}]({3})"{4});",
            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
            edmFunction.NamespaceName,
            edmFunction.Name,
            string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
            _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
    }
    
    public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
    {
        var parameters = _typeMapper.GetParameters(edmFunction);
        var returnType = _typeMapper.GetReturnType(edmFunction);

        var paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
        if (includeMergeOption)
        {
            paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
        }

        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1} {2}({3})",
            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
            returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
            _code.Escape(edmFunction),
            paramList);
    }
    
    public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
    {
        var parameters = _typeMapper.GetParameters(edmFunction);
        var returnType = _typeMapper.GetReturnType(edmFunction);

        var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
        if (includeMergeOption)
        {
            callParams = ", mergeOption" + callParams;
        }
        
        return string.Format(
            CultureInfo.InvariantCulture,
            "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}("{1}"{2});",
            returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
            edmFunction.Name,
            callParams);
    }
    
    public string DbSet(EntitySet entitySet)
    {
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} DbSet<{1}> {2} {{ get; set; }}",
            Accessibility.ForReadOnlyProperty(entitySet),
            _typeMapper.GetTypeName(entitySet.ElementType),
            _code.Escape(entitySet));
    }

    public string UsingDirectives(bool inHeader, bool includeCollections = true)
    {
        return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
            ? string.Format(
                CultureInfo.InvariantCulture,
                "{0}using System;{1}" +
                "{2}",
                inHeader ? Environment.NewLine : "",
                includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
                inHeader ? "" : Environment.NewLine)
            : "";
    }
}

public class TypeMapper
{
    private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";

    private readonly System.Collections.IList _errors;
    private readonly CodeGenerationTools _code;
    private readonly MetadataTools _ef;

    public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
    {
        ArgumentNotNull(code, "code");
        ArgumentNotNull(ef, "ef");
        ArgumentNotNull(errors, "errors");

        _code = code;
        _ef = ef;
        _errors = errors;
    }

    public string GetTypeName(TypeUsage typeUsage)
    {
        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
    }

    public string GetTypeName(EdmType edmType)
    {
        return GetTypeName(edmType, isNullable: null, modelNamespace: null);
    }

    public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
    {
        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
    }

    public string GetTypeName(EdmType edmType, string modelNamespace)
    {
        return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
    }

    public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
    {
        if (edmType == null)
        {
            return null;
        }

        var collectionType = edmType as CollectionType;
        if (collectionType != null)
        {
            return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
        }

        var typeName = _code.Escape(edmType.MetadataProperties
                                .Where(p => p.Name == ExternalTypeNameAttributeName)
                                .Select(p => (string)p.Value)
                                .FirstOrDefault())
            ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
                _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
                _code.Escape(edmType));

        if (edmType is StructuralType)
        {
            return typeName;
        }

        if (edmType is SimpleType)
        {
            var clrType = UnderlyingClrType(edmType);
            if (!IsEnumType(edmType))
            {
                typeName = _code.Escape(clrType);
            }

            return clrType.IsValueType && isNullable == true ?
                String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
                typeName;
        }

        throw new ArgumentException("edmType");
    }
    
    public Type UnderlyingClrType(EdmType edmType)
    {
        ArgumentNotNull(edmType, "edmType");

        var primitiveType = edmType as PrimitiveType;
        if (primitiveType != null)
        {
            return primitiveType.ClrEquivalentType;
        }

        if (IsEnumType(edmType))
        {
            return GetEnumUnderlyingType(edmType).ClrEquivalentType;
        }

        return typeof(object);
    }
    
    public object GetEnumMemberValue(MetadataItem enumMember)
    {
        ArgumentNotNull(enumMember, "enumMember");
        
        var valueProperty = enumMember.GetType().GetProperty("Value");
        return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
    }
    
    public string GetEnumMemberName(MetadataItem enumMember)
    {
        ArgumentNotNull(enumMember, "enumMember");
        
        var nameProperty = enumMember.GetType().GetProperty("Name");
        return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
    }

    public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
    {
        ArgumentNotNull(enumType, "enumType");

        var membersProperty = enumType.GetType().GetProperty("Members");
        return membersProperty != null 
            ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
            : Enumerable.Empty<MetadataItem>();
    }
    
    public bool EnumIsFlags(EdmType enumType)
    {
        ArgumentNotNull(enumType, "enumType");
        
        var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
        return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
    }

    public bool IsEnumType(GlobalItem edmType)
    {
        ArgumentNotNull(edmType, "edmType");

        return edmType.GetType().Name == "EnumType";
    }

    public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
    {
        ArgumentNotNull(enumType, "enumType");

        return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
    }

    public string CreateLiteral(object value)
    {
        if (value == null || value.GetType() != typeof(TimeSpan))
        {
            return _code.CreateLiteral(value);
        }

        return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
    }
    
    public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
    {
        ArgumentNotNull(types, "types");
        ArgumentNotNull(sourceFile, "sourceFile");
        
        var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
        if (types.Any(item => !hash.Add(item)))
        {
            _errors.Add(
                new CompilerError(sourceFile, -1, -1, "6023",
                    String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_CaseInsensitiveTypeConflict"))));
            return false;
        }
        return true;
    }
    
    public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
    {
        return GetItemsToGenerate<SimpleType>(itemCollection)
            .Where(e => IsEnumType(e));
    }
    
    public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
    {
        return itemCollection
            .OfType<T>()
            .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
            .OrderBy(i => i.Name);
    }

    public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
    {
        return itemCollection
            .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
            .Select(g => GetGlobalItemName(g));
    }

    public string GetGlobalItemName(GlobalItem item)
    {
        if (item is EdmType)
        {
            return ((EdmType)item).Name;
        }
        else
        {
            return ((EntityContainer)item).Name;
        }
    }

    public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
    }
    
    public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
    }
    
    public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
    }
    
    public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
    }

    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
    }
    
    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
    {
        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
    }

    public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
    {
        return type.NavigationProperties.Where(np => np.DeclaringType == type);
    }
    
    public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
    {
        return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
    }
    
    public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
    {
        ArgumentNotNull(edmFunction, "edmFunction");

        var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
        return returnParamsProperty == null
            ? edmFunction.ReturnParameter
            : ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
    }

    public bool IsComposable(EdmFunction edmFunction)
    {
        ArgumentNotNull(edmFunction, "edmFunction");

        var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
        return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
    }

    public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
    {
        return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
    }

    public TypeUsage GetReturnType(EdmFunction edmFunction)
    {
        var returnParam = GetReturnParameter(edmFunction);
        return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
    }
    
    public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
    {
        var returnType = GetReturnType(edmFunction);
        return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
    }
}

public class EdmMetadataLoader
{
    private readonly IDynamicHost _host;
    private readonly System.Collections.IList _errors;

    public EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)
    {
        ArgumentNotNull(host, "host");
        ArgumentNotNull(errors, "errors");

        _host = host;
        _errors = errors;
    }

    public IEnumerable<GlobalItem> CreateEdmItemCollection(string sourcePath)
    {
        ArgumentNotNull(sourcePath, "sourcePath");

        if (!ValidateInputPath(sourcePath))
        {
            return new EdmItemCollection();
        }

        var schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));
        if (schemaElement != null)
        {
            using (var reader = schemaElement.CreateReader())
            {
                IList<EdmSchemaError> errors;
                var itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(new[] { reader }, out errors);

                ProcessErrors(errors, sourcePath);

                return itemCollection;
            }
        }
        return new EdmItemCollection();
    }

    public string GetModelNamespace(string sourcePath)
    {
        ArgumentNotNull(sourcePath, "sourcePath");

        if (!ValidateInputPath(sourcePath))
        {
            return string.Empty;
        }

        var model = LoadRootElement(_host.ResolvePath(sourcePath));
        if (model == null)
        {
            return string.Empty;
        }

        var attribute = model.Attribute("Namespace");
        return attribute != null ? attribute.Value : "";
    }

    private bool ValidateInputPath(string sourcePath)
    {
        if (sourcePath == "$" + "edmxInputFile" + "$")
        {
            _errors.Add(
                new CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, string.Empty,
                    GetResourceString("Template_ReplaceVsItemTemplateToken")));
            return false;
        }

        return true;
    }

    public XElement LoadRootElement(string sourcePath)
    {
        ArgumentNotNull(sourcePath, "sourcePath");

        var root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
        return root.Elements()
            .Where(e => e.Name.LocalName == "Runtime")
            .Elements()
            .Where(e => e.Name.LocalName == "ConceptualModels")
            .Elements()
            .Where(e => e.Name.LocalName == "Schema")
            .FirstOrDefault()
                ?? root;
    }

    private void ProcessErrors(IEnumerable<EdmSchemaError> errors, string sourceFilePath)
    {
        foreach (var error in errors)
        {
            _errors.Add(
                new CompilerError(
                    error.SchemaLocation ?? sourceFilePath,
                    error.Line,
                    error.Column,
                    error.ErrorCode.ToString(CultureInfo.InvariantCulture),
                    error.Message)
                {
                    IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning
                });
        }
    }
    
    public bool IsLazyLoadingEnabled(EntityContainer container)
    {
        string lazyLoadingAttributeValue;
        var lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";
        bool isLazyLoading;
        return !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue)
            || !bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)
            || isLazyLoading;
    }
}

public static void ArgumentNotNull<T>(T arg, string name) where T : class
{
    if (arg == null)
    {
        throw new ArgumentNullException(name);
    }
}
    
private static readonly Lazy<System.Resources.ResourceManager> ResourceManager =
    new Lazy<System.Resources.ResourceManager>(
        () => new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(MetadataItemCollectionFactory).Assembly), isThreadSafe: true);

public static string GetResourceString(string resourceName)
{
    ArgumentNotNull(resourceName, "resourceName");

    return ResourceManager.Value.GetString(resourceName, null);
}

#>
OADBModel
原文地址:https://www.cnblogs.com/kiamer2425/p/EF.html