diff --git a/NuGet/linq2db.Access.nuspec b/NuGet/linq2db.Access.nuspec index 1357189..9b1bfcf 100644 --- a/NuGet/linq2db.Access.nuspec +++ b/NuGet/linq2db.Access.nuspec @@ -2,7 +2,7 @@ linq2db.Access - 1.9.0 + 1.10.0 LINQ to Access Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db Access LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.DB2.nuspec b/NuGet/linq2db.DB2.nuspec index 5bc9f11..f2ec47b 100644 --- a/NuGet/linq2db.DB2.nuspec +++ b/NuGet/linq2db.DB2.nuspec @@ -2,7 +2,7 @@ linq2db.DB2 - 1.9.0 + 1.10.0 LINQ to IBM DB2 Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db DB2 LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Firebird.nuspec b/NuGet/linq2db.Firebird.nuspec index 5542047..1b90058 100644 --- a/NuGet/linq2db.Firebird.nuspec +++ b/NuGet/linq2db.Firebird.nuspec @@ -2,7 +2,7 @@ linq2db.Firebird - 1.9.0 + 1.10.0 LINQ to Firebird Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db Firebird LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Informix.nuspec b/NuGet/linq2db.Informix.nuspec index 67c0c6e..c0ba8fa 100644 --- a/NuGet/linq2db.Informix.nuspec +++ b/NuGet/linq2db.Informix.nuspec @@ -2,7 +2,7 @@ linq2db.Informix - 1.9.0 + 1.10.0 LINQ to Informix Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db Informix LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.MySql.nuspec b/NuGet/linq2db.MySql.nuspec index 99af74a..4650112 100644 --- a/NuGet/linq2db.MySql.nuspec +++ b/NuGet/linq2db.MySql.nuspec @@ -2,7 +2,7 @@ linq2db.MySql - 1.9.0 + 1.10.0 LINQ to MySql Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db MySql LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Oracle.Managed.nuspec b/NuGet/linq2db.Oracle.Managed.nuspec index b09f1b8..61a4a89 100644 --- a/NuGet/linq2db.Oracle.Managed.nuspec +++ b/NuGet/linq2db.Oracle.Managed.nuspec @@ -2,7 +2,7 @@ linq2db.Oracle.Managed - 1.9.0 + 1.10.0 LINQ to Oracle (ODP.NET) Managed Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db Oracle LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Oracle.x64.nuspec b/NuGet/linq2db.Oracle.x64.nuspec index 2cc557a..1bee7bd 100644 --- a/NuGet/linq2db.Oracle.x64.nuspec +++ b/NuGet/linq2db.Oracle.x64.nuspec @@ -2,7 +2,7 @@ linq2db.Oracle.x64 - 1.9.0 + 1.10.0 LINQ to Oracle (ODP.NET) x64 Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db Oracle ODP LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Oracle.x86.nuspec b/NuGet/linq2db.Oracle.x86.nuspec index d7d4d8f..9f011c4 100644 --- a/NuGet/linq2db.Oracle.x86.nuspec +++ b/NuGet/linq2db.Oracle.x86.nuspec @@ -2,7 +2,7 @@ linq2db.Oracle.x86 - 1.9.0 + 1.10.0 LINQ to Oracle (ODP.NET) x86 Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db Oracle ODP LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.PostgreSQL.nuspec b/NuGet/linq2db.PostgreSQL.nuspec index 0ce55f8..03f6df2 100644 --- a/NuGet/linq2db.PostgreSQL.nuspec +++ b/NuGet/linq2db.PostgreSQL.nuspec @@ -2,7 +2,7 @@ linq2db.PostgreSQL - 1.9.0 + 1.10.0 LINQ to PostgreSQL Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db Npgsql PostgreSQL LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.SQLite.nuspec b/NuGet/linq2db.SQLite.nuspec index 4d56a66..7eb4964 100644 --- a/NuGet/linq2db.SQLite.nuspec +++ b/NuGet/linq2db.SQLite.nuspec @@ -2,7 +2,7 @@ linq2db.SQLite - 1.9.0 + 1.10.0 LINQ to SQLite Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db SQLite LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.SapHana.nuspec b/NuGet/linq2db.SapHana.nuspec index e482fb3..e699a53 100644 --- a/NuGet/linq2db.SapHana.nuspec +++ b/NuGet/linq2db.SapHana.nuspec @@ -2,7 +2,7 @@ linq2db.SapHana - 1.9.0 + 1.10.0 LINQ to SAP HANA Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db SapHana LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.SqlCe.nuspec b/NuGet/linq2db.SqlCe.nuspec index 5f0ff48..743c20f 100644 --- a/NuGet/linq2db.SqlCe.nuspec +++ b/NuGet/linq2db.SqlCe.nuspec @@ -2,7 +2,7 @@ linq2db.SqlCe - 1.9.0 + 1.10.0 LINQ to SqlCe Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db SqlCe SqlServerCe SqlServer Compact LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.SqlServer.nuspec b/NuGet/linq2db.SqlServer.nuspec index 1f1be4c..8b1bafe 100644 --- a/NuGet/linq2db.SqlServer.nuspec +++ b/NuGet/linq2db.SqlServer.nuspec @@ -2,7 +2,7 @@ linq2db.SqlServer - 1.9.0 + 1.10.0 LINQ to SqlServer Igor Tkachev @@ -18,7 +18,7 @@ linq linq2db SqlServer LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.Sybase.nuspec b/NuGet/linq2db.Sybase.nuspec index d9bc74e..8a6cd54 100644 --- a/NuGet/linq2db.Sybase.nuspec +++ b/NuGet/linq2db.Sybase.nuspec @@ -2,7 +2,7 @@ linq2db.Sybase - 1.9.0 + 1.10.0 LINQ to Sybase ASE Igor Tkachev @@ -19,7 +19,7 @@ linq linq2db Sybase LinqToDB ORM database DB SQL - + diff --git a/NuGet/linq2db.t4models.nuspec b/NuGet/linq2db.t4models.nuspec index b7e5e33..ff417bb 100644 --- a/NuGet/linq2db.t4models.nuspec +++ b/NuGet/linq2db.t4models.nuspec @@ -2,7 +2,7 @@ linq2db.t4models - 1.9.0 + 1.10.0 LINQ to DB T4 Models Igor Tkachev @@ -23,17 +23,17 @@ - + - + - + diff --git a/T4Models.sln b/T4Models.sln index 7163b2f..1ef7dde 100644 --- a/T4Models.sln +++ b/T4Models.sln @@ -22,6 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Templates", "Templates", "{ Templates\LinqToDB.SqlServer.ttinclude = Templates\LinqToDB.SqlServer.ttinclude Templates\LinqToDB.Sybase.ttinclude = Templates\LinqToDB.Sybase.ttinclude Templates\LinqToDB.ttinclude = Templates\LinqToDB.ttinclude + Templates\MultipleFiles.ttinclude = Templates\MultipleFiles.ttinclude Templates\NotifyPropertyChanged.ttinclude = Templates\NotifyPropertyChanged.ttinclude Templates\ObsoleteAttributes.ttinclude = Templates\ObsoleteAttributes.ttinclude Templates\PluralizationService.ttinclude = Templates\PluralizationService.ttinclude diff --git a/Templates/DataModel.ttinclude b/Templates/DataModel.ttinclude index 69aa208..95e6f52 100644 --- a/Templates/DataModel.ttinclude +++ b/Templates/DataModel.ttinclude @@ -83,6 +83,18 @@ static Func ConvertColumnMemberType static Func ConvertTableColumnMemberType = (t,c) => ConvertColumnMemberType(c); static Func ConvertProcedureColumnMemberType = (t,c) => ConvertColumnMemberType(c); +HashSet KeyWords = new HashSet +{ + "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", + "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", + "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", + "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "new", + "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", + "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "struct", "switch", + "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", + "using", "virtual", "volatile", "void", "while", "namespace", "string" +}; + void LoadServerMetadata(DataConnection dataConnection) { SqlBuilder = dataConnection.DataProvider.CreateSqlBuilder(); @@ -114,12 +126,8 @@ void LoadServerMetadata(DataConnection dataConnection) Schema = (t.IsDefaultSchema && !IncludeDefaultSchema) || string.IsNullOrEmpty(t.SchemaName)? null : t.SchemaName, BaseClass = BaseEntityClass, TableName = t.TableName, - TypeName = - PluralizeClassNames ? ToPlural (t.TypeName) : - SingularizeClassNames ? ToSingular(t.TypeName) : t.TypeName, - DataContextPropertyName = - PluralizeDataContextPropertyNames ? ToPlural (t.TypeName) : - SingularizeDataContextPropertyNames ? ToSingular(t.TypeName) : t.TypeName, + TypeName = t.TypeName, + DataContextPropertyName = t.TypeName, IsView = t.IsView, IsProviderSpecific = false, Description = t.Description, @@ -147,6 +155,48 @@ void LoadServerMetadata(DataConnection dataConnection) }) .ToList(); + if (PluralizeClassNames || SingularizeClassNames) + { + var foundNames = new HashSet(tables.Select(t => t.table.TypeName)); + foreach (var t in tables) + { + var newName = t.table.TypeName; + newName = + PluralizeClassNames ? ToPlural (newName) : + SingularizeClassNames ? ToSingular(newName) : newName; + + if (newName != t.table.TypeName) + { + if (!foundNames.Contains(newName)) + { + t.table.TypeName = newName; + foundNames.Add(newName); + } + } + } + } + + if (PluralizeDataContextPropertyNames || SingularizeDataContextPropertyNames) + { + var foundNames = new HashSet(tables.Select(t => t.table.DataContextPropertyName)); + foreach (var t in tables) + { + var newName = t.table.DataContextPropertyName; + newName = + PluralizeDataContextPropertyNames ? ToPlural (newName) : + SingularizeDataContextPropertyNames ? ToSingular(newName) : newName; + + if (newName != t.table.TypeName) + { + if (!foundNames.Contains(newName)) + { + t.table.DataContextPropertyName = newName; + foundNames.Add(newName); + } + } + } + } + tables.AddRange(db.Tables .Where(t => t.IsProviderSpecific) .Select(t => new @@ -185,17 +235,21 @@ void LoadServerMetadata(DataConnection dataConnection) foreach (var key in keys) { + var keyName = key.k.OtherTable.IsDefaultSchema ? key.KeyName : key.k.OtherTable.SchemaName + "." + key.KeyName; + ForeignKey foundKey; + if (key.t.table.ForeignKeys.TryGetValue(keyName, out foundKey)) + { + key.t.table.ForeignKeys.Remove(keyName); + key.t.table.ForeignKeys.Add(foundKey.OtherTable.TableName + "." + keyName, foundKey); + keyName = key.k.OtherTable.TableName + "." + keyName; + } + key.t.table.ForeignKeys.Add( key.k.OtherTable.IsDefaultSchema ? key.KeyName : key.k.OtherTable.SchemaName + "." + key.KeyName, key.key); if (key.k.BackReference != null) key.key.BackReference = keys.First(k => k.k == key.k.BackReference).key; - - key.key.MemberName = key.key.MemberName.Replace(".", String.Empty); - - key.key.MemberName = key.key.AssociationType == AssociationType.OneToMany ? - ToPlural(key.key.MemberName) : ToSingular(key.key.MemberName); } var procedures = db.Procedures @@ -326,8 +380,8 @@ string CheckColumnName(string memberName) .Replace(".", "_") .Replace("\u00A3", "Pound"); - if (memberName == "new") - memberName = "@new"; + if (KeyWords.Contains(memberName)) + memberName = "@" + memberName; } return memberName; } @@ -363,24 +417,12 @@ void LoadMetadata(DataConnection dataConnection) if (Tables.Values.SelectMany(_ => _.ForeignKeys.Values).Any(_ => _.AssociationType == AssociationType.OneToMany)) Model.Usings.Add("System.Collections.Generic"); - var keyWords = new HashSet - { - "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", - "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", - "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", - "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "new", - "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", - "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "struct", "switch", - "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", - "using", "virtual", "volatile", "void", "while", "namespace", "string" - }; - foreach (var t in Tables.Values) { - if (keyWords.Contains(t.TypeName)) + if (KeyWords.Contains(t.TypeName)) t.TypeName = "@" + t.TypeName; - if (keyWords.Contains(t.DataContextPropertyName)) + if (KeyWords.Contains(t.DataContextPropertyName)) t.DataContextPropertyName = "@" + t.DataContextPropertyName; t.TypeName = ConvertToCompilable(t.TypeName, true); @@ -388,7 +430,7 @@ void LoadMetadata(DataConnection dataConnection) foreach (var col in t.Columns.Values) { - if (keyWords.Contains(col.MemberName)) + if (KeyWords.Contains(col.MemberName)) col.MemberName = "@" + col.MemberName; col.MemberName = ConvertToCompilable(col.MemberName, true); @@ -396,34 +438,96 @@ void LoadMetadata(DataConnection dataConnection) if (col.MemberName == t.TypeName) col.MemberName += "_Column"; } + } + + foreach (var t in Tables.Values) + { + foreach (var fk in t.ForeignKeys.Values) + { + var memberName = fk.OtherTable.TypeName; + + memberName = fk.AssociationType == AssociationType.OneToMany ? + ToPlural(memberName) : ToSingular(memberName); + + fk.MemberName = memberName; + } + } - var duplicates = t.Columns.Values.ToLookup(c => c.MemberName).Where(g => g.Count() > 1); - foreach (var d in duplicates) - { - var alreadyNamed = new HashSet(); - foreach (var col in d) - { - col.MemberName = col.ColumnName; - if (keyWords.Contains(col.MemberName)) - col.MemberName = "@" + col.MemberName; - - col.MemberName = ConvertToCompilable(col.MemberName, false); - - if (col.MemberName == t.TypeName) - col.MemberName += "_Column"; - - while (alreadyNamed.Contains(col.MemberName)) - { - col.MemberName += "_"; - } - alreadyNamed.Add(col.MemberName); - } - } + foreach (var t in Tables.Values) + { + var forbidden = KeyWords.Concat(new [] {t.TypeName}); + + var hasDuplicates = t.Columns.Values + .Select(c => c.MemberName) + .Concat(t.ForeignKeys.Values.Select(f => f.MemberName)) + .Concat(forbidden) + .ToLookup(n => n) + .Any(g => g.Count() > 1); + + if (hasDuplicates) + { + foreach (var fk in t.ForeignKeys.Values) + { + var mayDuplicate = t.Columns.Values + .Select(c => c.MemberName) + .Concat(forbidden) + .Concat(t.ForeignKeys.Values.Where(f => f != fk).Select(f => f.MemberName)); + + fk.MemberName = SuggestNoDuplicate(mayDuplicate, fk.MemberName, "FK"); + } + + foreach (var col in t.Columns.Values) + { + var mayDuplicate = t.Columns.Values + .Where(c => c != col) + .Select(c => c.MemberName) + .Concat(forbidden) + .Concat(t.ForeignKeys.Values.Select(fk => fk.MemberName)); + + col.MemberName = SuggestNoDuplicate(mayDuplicate, col.MemberName, null); + } + } } AfterLoadMetadata(); } +string SuggestNoDuplicate(IEnumerable currentNames, string newName, string prefix) +{ + var names = new HashSet(currentNames); + var result = newName; + if (names.Contains(result)) + { + if (!string.IsNullOrEmpty(prefix)) + result = prefix + result; + if (names.Contains(result)) + { + var counter = 0; + var number = string.Concat(result.Reverse().Take(6).TakeWhile(c => Char.IsDigit(c)).Reverse()); + if (!string.IsNullOrEmpty(number)) + { + if (int.TryParse(number, out counter)) + { + result = result.Remove(result.Length - number.Length); + } + } + + do + { + ++counter; + if (!names.Contains(result + counter)) + { + result = result + counter; + break; + } + } + while(true); + } + } + + return result; +} + string ConvertToCompilableDefault(string name, bool mayRemoveUnderscore) { var query = diff --git a/Templates/LinqToDB.ttinclude b/Templates/LinqToDB.ttinclude index 9e88d9c..efa6700 100644 --- a/Templates/LinqToDB.ttinclude +++ b/Templates/LinqToDB.ttinclude @@ -874,7 +874,9 @@ void GenerateTypesFromMetadata() string NormalizeStringName(string name) { - return @"@""" + name.Replace(@"""", @"""""") + @""""; + if (name.Contains("\"") || name.Contains("\\")) + return @"@""" + name.Replace(@"""", @"""""") + @""""; + return "\"" + name + "\""; } #> diff --git a/Templates/MultipleFiles.ttinclude b/Templates/MultipleFiles.ttinclude new file mode 100644 index 0000000..1cb3a5e --- /dev/null +++ b/Templates/MultipleFiles.ttinclude @@ -0,0 +1,70 @@ +<#@ assembly name="System.Core" #> +<#@ assembly name="EnvDTE" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="EnvDTE" #> +<#+ +DTE _dte; +DTE DTE => _dte ?? (_dte = (DTE)((IServiceProvider)Host).GetService(typeof(DTE))); + +ProjectItem _templateProjectItem; +ProjectItem TemplateProjectItem => _templateProjectItem ?? (_templateProjectItem = DTE.Solution.FindProjectItem(Host.TemplateFile)); + +readonly Dictionary _fileNames = new Dictionary(); + +Func CompareContent = (s1,s2) => s1 == s2; + +void SaveOutput(string fileName, int fileType = 1) +{ + var dir = Path.GetDirectoryName(Host.TemplateFile); + var output = Path.Combine(dir, fileName); + var newContent = GenerationEnvironment.ToString(); + var oldContent = File.Exists(output) ? File.ReadAllText(output) : ""; + + if (!CompareContent(newContent, oldContent)) + { + if (DTE.SourceControl != null && DTE.SourceControl.IsItemUnderSCC(output) && !DTE.SourceControl.IsItemCheckedOut(output)) + DTE.SourceControl.CheckOutItem(output); + + File.WriteAllText(output, newContent); + } + + GenerationEnvironment.Length = 0; + + _fileNames.Add(output, fileType); +} + +void SyncProject() +{ + var keepFileNames = _fileNames.ToDictionary(f => f.Key); + var projectFiles = new Dictionary(); + var templateFileName = TemplateProjectItem.FileNames[0]; + var originalFilePrefix = Path.GetFileNameWithoutExtension(templateFileName) + "."; + + foreach (ProjectItem projectItem in TemplateProjectItem.ProjectItems) + { + projectFiles.Add(projectItem.FileNames[0], projectItem); + } + + foreach (var pair in projectFiles) + { + if (!keepFileNames.ContainsKey(pair.Key)) + if (!(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(originalFilePrefix)) + //if (pair.Key != templateFileName) + pair.Value.Delete(); + } + + // Add missing files to the project. + // + foreach (var fileName in keepFileNames) + { + if (!projectFiles.ContainsKey(fileName.Value.Key)) + if (File.Exists(fileName.Value.Key)) + { + var newItem = TemplateProjectItem.ProjectItems.AddFromFile(fileName.Value.Key); + newItem.Properties.Item("BuildAction").Value = fileName.Value.Value; + } + } +} +#> diff --git a/Templates/ObsoleteAttributes.ttinclude b/Templates/ObsoleteAttributes.ttinclude index 9e4808c..94f1b05 100644 --- a/Templates/ObsoleteAttributes.ttinclude +++ b/Templates/ObsoleteAttributes.ttinclude @@ -1,18 +1,18 @@ -<# - { - var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel; - var afterGenerateLinqToDBModel = AfterGenerateLinqToDBModel; - - var obsoleteTables = new List>(); - - BeforeGenerateLinqToDBModel = () => - { - beforeGenerateLinqToDBModel(); - - foreach (var table in Tables.Values) - { - var idx = table.Description.IndexOf("[Obsolete"); - +<# + { + var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel; + var afterGenerateLinqToDBModel = AfterGenerateLinqToDBModel; + + var obsoleteTables = new List>(); + + BeforeGenerateLinqToDBModel = () => + { + beforeGenerateLinqToDBModel(); + + foreach (var table in Tables.Values) + { + var idx = table.Description.IndexOf("[Obsolete"); + if (idx >= 0) { var idx2 = table.Description.IndexOf(']', idx); @@ -24,77 +24,77 @@ var info = Tuple.Create(table.Schema, table.Name, text); if (obsoleteTables.All(a => a != info)) - obsoleteTables.Add(info); - table.Attributes.Add(attr); + obsoleteTables.Add(info); + table.Attributes.Add(attr); table.Description = table.Description.Substring(0, idx) + table.Description.Substring(idx2 + 1); } - } - - foreach (var c in table.Columns.Values) - { - idx = c.Description.IndexOf("[Obsolete"); - - if (idx >= 0) - { + } + + foreach (var c in table.Columns.Values) + { + idx = c.Description.IndexOf("[Obsolete"); + + if (idx >= 0) + { var idx2 = c.Description.IndexOf(']', idx); if (idx2 > idx) { var attr = new Attribute(c.Description.Substring(idx + 1, idx2 - idx - 1)); - c.Attributes.Add(attr); + c.Attributes.Add(attr); c.Description = c.Description.Substring(0, idx) + c.Description.Substring(idx2 + 1); } - } - } - } - }; - - AfterGenerateLinqToDBModel = () => - { - foreach (var tableInfo in obsoleteTables) - { - var schema = tableInfo.Item1; - var name = tableInfo.Item2; - var text = tableInfo.Item3; - var obsoleteAttr = new Attribute(text); - - foreach (var cm in GetTreeNodes(Model) - .OfType() - .Where(t => t.Type != null) - .Where(t => t.Type == name || t.Type.Contains("<" + name + ">"))) - { - // check schema - - if (cm.Parent != null && cm.Parent.Parent != null) - { - var parent = cm.Parent.Parent; - - if (parent is Table) - { - var table = (Table)parent; - - if (schema == table.Schema) - if (cm.Attributes.All(a => a.Name != text)) - cm.Attributes.Add(obsoleteAttr); - } - else if (parent is Class) - { - var cls = (Class)parent; - - bool parentClassIncludesSchemaName = cls.Name.Equals(schema + "Schema", StringComparison.InvariantCultureIgnoreCase); - bool classIsForDefaultSchema = cls.Name == DataContextName; - bool isExtensionMethod = cls.Parent is Namespace || cls.Name == "TableExtensions"; - - if (classIsForDefaultSchema || parentClassIncludesSchemaName || isExtensionMethod) - if (cm.Attributes.All(a => a.Name != text)) - cm.Attributes.Add(obsoleteAttr); - } - } - } - } - - afterGenerateLinqToDBModel(); - }; - } -#> + } + } + } + }; + + AfterGenerateLinqToDBModel = () => + { + foreach (var tableInfo in obsoleteTables) + { + var schema = tableInfo.Item1; + var name = tableInfo.Item2; + var text = tableInfo.Item3; + var obsoleteAttr = new Attribute(text); + + foreach (var cm in GetTreeNodes(Model) + .OfType() + .Where(t => t.Type != null) + .Where(t => t.Type == name || t.Type.Contains("<" + name + ">"))) + { + // check schema + + if (cm.Parent != null && cm.Parent.Parent != null) + { + var parent = cm.Parent.Parent; + + if (parent is Table) + { + var table = (Table)parent; + + if (schema == table.Schema) + if (cm.Attributes.All(a => a.Name != text)) + cm.Attributes.Add(obsoleteAttr); + } + else if (parent is Class) + { + var cls = (Class)parent; + + bool parentClassIncludesSchemaName = cls.Name.Equals(schema + "Schema", StringComparison.InvariantCultureIgnoreCase); + bool classIsForDefaultSchema = cls.Name == DataContextName; + bool isExtensionMethod = cls.Parent is Namespace || cls.Name == "TableExtensions"; + + if (classIsForDefaultSchema || parentClassIncludesSchemaName || isExtensionMethod) + if (cm.Attributes.All(a => a.Name != text)) + cm.Attributes.Add(obsoleteAttr); + } + } + } + } + + afterGenerateLinqToDBModel(); + }; + } +#> diff --git a/Tests/LinqToDB/SQLite.generated.cs b/Tests/LinqToDB/SQLite.generated.cs index eabe5f0..e267eb6 100644 --- a/Tests/LinqToDB/SQLite.generated.cs +++ b/Tests/LinqToDB/SQLite.generated.cs @@ -47,29 +47,29 @@ public TestDataDB(string configuration) [Table("AllTypes")] public partial class AllType { - [Column(), PrimaryKey, Identity] public long ID { get; set; } // integer - [Column(@"bigintDataType"), Nullable ] public long? BigintDataType { get; set; } // bigint - [Column(@"numericDataType"), Nullable ] public decimal? NumericDataType { get; set; } // numeric - [Column(@"bitDataType"), Nullable ] public bool? BitDataType { get; set; } // bit - [Column(@"smallintDataType"), Nullable ] public short? SmallintDataType { get; set; } // smallint - [Column(@"decimalDataType"), Nullable ] public decimal? DecimalDataType { get; set; } // decimal - [Column(@"intDataType"), Nullable ] public int? IntDataType { get; set; } // int - [Column(@"tinyintDataType"), Nullable ] public byte? TinyintDataType { get; set; } // tinyint - [Column(@"moneyDataType"), Nullable ] public decimal? MoneyDataType { get; set; } // money - [Column(@"floatDataType"), Nullable ] public double? FloatDataType { get; set; } // float - [Column(@"realDataType"), Nullable ] public double? RealDataType { get; set; } // real - [Column(@"datetimeDataType"), Nullable ] public DateTime? DatetimeDataType { get; set; } // datetime - [Column(@"charDataType"), Nullable ] public char? CharDataType { get; set; } // char(1) - [Column(@"varcharDataType"), Nullable ] public string VarcharDataType { get; set; } // varchar(20) - [Column(@"textDataType"), Nullable ] public string TextDataType { get; set; } // text(max) - [Column(@"ncharDataType"), Nullable ] public string NcharDataType { get; set; } // char(20) - [Column(@"nvarcharDataType"), Nullable ] public string NvarcharDataType { get; set; } // nvarchar(20) - [Column(@"ntextDataType"), Nullable ] public string NtextDataType { get; set; } // ntext(max) - [Column(@"binaryDataType"), Nullable ] public byte[] BinaryDataType { get; set; } // binary - [Column(@"varbinaryDataType"), Nullable ] public byte[] VarbinaryDataType { get; set; } // varbinary - [Column(@"imageDataType"), Nullable ] public byte[] ImageDataType { get; set; } // image - [Column(@"uniqueidentifierDataType"), Nullable ] public Guid? UniqueidentifierDataType { get; set; } // uniqueidentifier - [Column(@"objectDataType"), Nullable ] public object ObjectDataType { get; set; } // object + [Column(), PrimaryKey, Identity] public long ID { get; set; } // integer + [Column("bigintDataType"), Nullable ] public long? BigintDataType { get; set; } // bigint + [Column("numericDataType"), Nullable ] public decimal? NumericDataType { get; set; } // numeric + [Column("bitDataType"), Nullable ] public bool? BitDataType { get; set; } // bit + [Column("smallintDataType"), Nullable ] public short? SmallintDataType { get; set; } // smallint + [Column("decimalDataType"), Nullable ] public decimal? DecimalDataType { get; set; } // decimal + [Column("intDataType"), Nullable ] public int? IntDataType { get; set; } // int + [Column("tinyintDataType"), Nullable ] public byte? TinyintDataType { get; set; } // tinyint + [Column("moneyDataType"), Nullable ] public decimal? MoneyDataType { get; set; } // money + [Column("floatDataType"), Nullable ] public double? FloatDataType { get; set; } // float + [Column("realDataType"), Nullable ] public double? RealDataType { get; set; } // real + [Column("datetimeDataType"), Nullable ] public DateTime? DatetimeDataType { get; set; } // datetime + [Column("charDataType"), Nullable ] public char? CharDataType { get; set; } // char(1) + [Column("varcharDataType"), Nullable ] public string VarcharDataType { get; set; } // varchar(20) + [Column("textDataType"), Nullable ] public string TextDataType { get; set; } // text(max) + [Column("ncharDataType"), Nullable ] public string NcharDataType { get; set; } // char(20) + [Column("nvarcharDataType"), Nullable ] public string NvarcharDataType { get; set; } // nvarchar(20) + [Column("ntextDataType"), Nullable ] public string NtextDataType { get; set; } // ntext(max) + [Column("binaryDataType"), Nullable ] public byte[] BinaryDataType { get; set; } // binary + [Column("varbinaryDataType"), Nullable ] public byte[] VarbinaryDataType { get; set; } // varbinary + [Column("imageDataType"), Nullable ] public byte[] ImageDataType { get; set; } // image + [Column("uniqueidentifierDataType"), Nullable ] public Guid? UniqueidentifierDataType { get; set; } // uniqueidentifier + [Column("objectDataType"), Nullable ] public object ObjectDataType { get; set; } // object } [Table("Child")] diff --git a/Tests/LinqToDB/SQLite.tt b/Tests/LinqToDB/SQLite.tt index a5a8ca4..1522cab 100644 --- a/Tests/LinqToDB/SQLite.tt +++ b/Tests/LinqToDB/SQLite.tt @@ -3,7 +3,7 @@ <#@ include file="..\..\Templates\LinqToDB.SQLite.ttinclude" #> <#@ include file="..\..\Templates\PluralizationService.ttinclude" #> <#@ assembly name="$(SolutionDir)Tests\LinqToDB\bin\Debug\System.Data.SQLite.dll" #> -<#@ assembly name="$(SolutionDir)\packages\linq2db.1.9.0\lib\net40\linq2db.dll" #> +<#@ assembly name="$(SolutionDir)\packages\linq2db.1.10.0\lib\net40\linq2db.dll" #> <# NamespaceName = "SQLiteDataContext"; diff --git a/Tests/LinqToDB/SqlCe.tt b/Tests/LinqToDB/SqlCe.tt index e2c1172..66292fa 100644 --- a/Tests/LinqToDB/SqlCe.tt +++ b/Tests/LinqToDB/SqlCe.tt @@ -2,7 +2,7 @@ <#@ output extension=".generated.cs" #> <#@ include file="..\..\Templates\LinqToDB.SqlCe.ttinclude" #> <#@ assembly name="$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll" #> -<#@ assembly name="$(SolutionDir)\packages\linq2db.1.9.0\lib\net40\linq2db.dll" #> +<#@ assembly name="$(SolutionDir)\packages\linq2db.1.10.0\lib\net40\linq2db.dll" #> <#@ include file="..\..\Templates\Humanizer.ttinclude" #> <#@ assembly name="$(SolutionDir)\packages\Humanizer.Core.2.2.0\lib\netstandard1.0\Humanizer.dll" #> <# diff --git a/Tests/LinqToDB/SqlServer.tt b/Tests/LinqToDB/SqlServer.tt index 5ce46ac..4076d5a 100644 --- a/Tests/LinqToDB/SqlServer.tt +++ b/Tests/LinqToDB/SqlServer.tt @@ -5,7 +5,7 @@ <#@ include file="..\..\Templates\ObsoleteAttributes.ttinclude" #> <#@ include file="SqlServer.ttinclude" #> <#@ assembly name="$(SolutionDir)\packages\Microsoft.SqlServer.Types.14.0.314.76\lib\net40\Microsoft.SqlServer.Types.dll" #> -<#@ assembly name="$(SolutionDir)\packages\linq2db.1.8.3\lib\net40\linq2db.dll" #> +<#@ assembly name="$(SolutionDir)\packages\linq2db.1.10.0\lib\net40\linq2db.dll" #> <# // NamespaceName = "DataContext"; // DataContextName = "NorthwindDB"; diff --git a/Tests/LinqToDB/T4Model.LinqToDB.csproj b/Tests/LinqToDB/T4Model.LinqToDB.csproj index 06bd744..ca7e883 100644 --- a/Tests/LinqToDB/T4Model.LinqToDB.csproj +++ b/Tests/LinqToDB/T4Model.LinqToDB.csproj @@ -44,8 +44,8 @@ ..\..\packages\Humanizer.Core.2.2.0\lib\netstandard1.0\Humanizer.dll - - ..\..\packages\linq2db.1.9.0\lib\net45\linq2db.dll + + ..\..\packages\linq2db.1.10.0\lib\net45\linq2db.dll ..\..\packages\Microsoft.SqlServer.Types.14.0.314.76\lib\Net40\Microsoft.SqlServer.Types.dll diff --git a/Tests/LinqToDB/packages.config b/Tests/LinqToDB/packages.config index 8af4615..049f565 100644 --- a/Tests/LinqToDB/packages.config +++ b/Tests/LinqToDB/packages.config @@ -2,7 +2,7 @@ - + diff --git a/Tests/Tests/MultipleFiles.generated.cs b/Tests/Tests/MultipleFiles.generated.cs new file mode 100644 index 0000000..dbb8d5e --- /dev/null +++ b/Tests/Tests/MultipleFiles.generated.cs @@ -0,0 +1,6 @@ +//--------------------------------------------------------------------------------------------------- +// +// This code was generated by T4 template. +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//--------------------------------------------------------------------------------------------------- diff --git a/Tests/Tests/MultipleFiles.tt b/Tests/Tests/MultipleFiles.tt new file mode 100644 index 0000000..01da485 --- /dev/null +++ b/Tests/Tests/MultipleFiles.tt @@ -0,0 +1,29 @@ +<#@ template language="C#" debug="True" hostSpecific="True" #> +<#@ output extension=".generated.cs" #> +<#@ include file="..\..\Templates\MultipleFiles.ttinclude" #> +//--------------------------------------------------------------------------------------------------- +// +// This code was generated by T4 template. +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//--------------------------------------------------------------------------------------------------- +<# + SaveOutput("aaa.cs", 1); +#> +//--------------------------------------------------------------------------------------------------- +// +// This code was generated by T4 template. +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//--------------------------------------------------------------------------------------------------- +<# + SaveOutput("bbb.txt", 2); + + SyncProject(); +#> +//--------------------------------------------------------------------------------------------------- +// +// This code was generated by T4 template. +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//--------------------------------------------------------------------------------------------------- diff --git a/Tests/Tests/T4Model.Tests.csproj b/Tests/Tests/T4Model.Tests.csproj index bf25c3d..c5f4d56 100644 --- a/Tests/Tests/T4Model.Tests.csproj +++ b/Tests/Tests/T4Model.Tests.csproj @@ -41,6 +41,9 @@ + + MultipleFiles.tt + EditableModelTest.tt True @@ -52,6 +55,11 @@ True ModelTest.tt + + True + True + MultipleFiles.tt + @@ -67,6 +75,17 @@ + + + TextTemplatingFileGenerator + MultipleFiles.generated.cs + + + + + MultipleFiles.tt + +