diff options
Diffstat (limited to 'ComicRackWebViewer/LinqToDB.Templates/DataModel.ttinclude')
-rw-r--r-- | ComicRackWebViewer/LinqToDB.Templates/DataModel.ttinclude | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/ComicRackWebViewer/LinqToDB.Templates/DataModel.ttinclude b/ComicRackWebViewer/LinqToDB.Templates/DataModel.ttinclude new file mode 100644 index 0000000..6295538 --- /dev/null +++ b/ComicRackWebViewer/LinqToDB.Templates/DataModel.ttinclude @@ -0,0 +1,502 @@ +<#@ assembly name="System.Data" #> +<#@ import namespace="System.Data" #> +<#@ import namespace="LinqToDB.Data" #> +<#@ include file="T4Model.ttinclude" #> +<# + { + var beforeGenerateModel = BeforeGenerateModel; + BeforeGenerateModel = () => + { + GenerateTypesFromMetadata(); + beforeGenerateModel(); + }; + } +#><#+ + +string NamespaceName +{ + get { return Model.Namespace.Name; } + set { Model.Namespace.Name = value; } +} + +string DatabaseName = null; +string DataContextName = null; +string BaseDataContextClass = null; +string BaseEntityClass = null; +string OneToManyAssociationType = "IEnumerable<{0}>"; + +string[] DatabaseQuote = null; + +bool GenerateDatabaseName = false; +bool GenerateConstructors = true; +string DefaultConfiguration = null; +bool GenerateAssociations = true; +bool GenerateBackReferences = true; +bool ReplaceSimilarTables = true; +bool IncludeDefaultSchema = true; + +Class DataContextObject; + +bool PluralizeClassNames = false; +bool SingularizeClassNames = true; +bool PluralizeDataContextPropertyNames = true; +bool SingularizeDataContextPropertyNames = false; + +LinqToDB.SchemaProvider.GetSchemaOptions GetSchemaOptions = + new LinqToDB.SchemaProvider.GetSchemaOptions(); + +LinqToDB.SqlProvider.ISqlBuilder SqlBuilder; + +void LoadServerMetadata(DataConnection dataConnection) +{ + SqlBuilder = dataConnection.DataProvider.CreateSqlBuilder(); + + var sp = dataConnection.DataProvider.GetSchemaProvider(); + var db = sp.GetSchema(dataConnection, GetSchemaOptions); + + if (DatabaseName == null && GenerateDatabaseName) + DatabaseName = db.Database; + + if (DataContextName == null) + DataContextObject.Name = DataContextName = db.Database + "DB"; + + DataContextObject.Comment.Add("/ <summary>"); + DataContextObject.Comment.Add("/ Database : " + db.Database); + DataContextObject.Comment.Add("/ Data Source : " + db.DataSource); + DataContextObject.Comment.Add("/ Server Version : " + db.ServerVersion); + DataContextObject.Comment.Add("/ </summary>"); + + var tables = db.Tables + .Select(t => new + { + t, + key = t.IsDefaultSchema ? t.TableName : t.SchemaName + "." + t.TableName, + table = new Table + { + 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, + IsView = t.IsView, + Description = t.Description, + Columns = t.Columns.ToDictionary( + c => c.ColumnName, + c => new Column + { + ColumnName = c.ColumnName, + ColumnType = c.ColumnType, + IsNullable = c.IsNullable, + IsIdentity = c.IsIdentity, + IsPrimaryKey = c.IsPrimaryKey, + PrimaryKeyOrder = c.PrimaryKeyOrder, + MemberName = CheckType(c.SystemType, c.MemberName), + Type = c.MemberType, + SkipOnInsert = c.SkipOnInsert, + SkipOnUpdate = c.SkipOnUpdate, + Description = c.Description, + }) + } + }) + .ToList(); + + foreach (var t in tables) + Tables.Add(t.key, t.table); + + var keys = + ( + from t in tables + from k in t.t.ForeignKeys + let otherTable = tables.Where(tbl => tbl.t == k.OtherTable).Select(tbl => tbl.table).Single() + select new + { + k, + k.KeyName, + t, + key = new ForeignKey + { + KeyName = k.KeyName, + OtherTable = otherTable, + OtherColumns = k.OtherColumns.Select(c => otherTable.Columns[c.ColumnName]).ToList(), + ThisColumns = k.ThisColumns. Select(c => t.table. Columns[c.ColumnName]).ToList(), + CanBeNull = k.CanBeNull, + MemberName = k.MemberName, + AssociationType = (AssociationType)(int)k.AssociationType, + } + } + ).ToList(); + + foreach (var key in keys) + { + key.t.table.ForeignKeys.Add(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.AssociationType == AssociationType.OneToMany ? + ToPlural(key.key.MemberName) : ToSingular(key.key.MemberName); + } + + var procedures = db.Procedures + .Select(p => new + { + p, + key = p.IsDefaultSchema ? p.ProcedureName : p.SchemaName + "." + p.ProcedureName, + proc = new Procedure + { + Schema = (p.IsDefaultSchema && !IncludeDefaultSchema) || string.IsNullOrEmpty(p.SchemaName)? null : p.SchemaName, + ProcedureName = p.ProcedureName, + Name = p.MemberName, + IsFunction = p.IsFunction, + IsTableFunction = p.IsTableFunction, + IsDefaultSchema = p.IsDefaultSchema, + ResultTable = p.ResultTable == null ? null : + new Table + { + TypeName = + PluralizeClassNames ? ToPlural (p.ResultTable.TypeName) : + SingularizeClassNames ? ToSingular(p.ResultTable.TypeName) : p.ResultTable.TypeName, + Columns = ToDictionary( + p.ResultTable.Columns, + c => c.ColumnName, + c => new Column + { + ColumnName = c.ColumnName, + ColumnType = c.ColumnType, + IsNullable = c.IsNullable, + IsIdentity = c.IsIdentity, + IsPrimaryKey = c.IsPrimaryKey, + PrimaryKeyOrder = c.PrimaryKeyOrder, + MemberName = CheckType(c.SystemType, c.MemberName), + Type = c.MemberType, + SkipOnInsert = c.SkipOnInsert, + SkipOnUpdate = c.SkipOnUpdate, + Description = c.Description, + }, + (c,n) => + { + c.IsDuplicateOrEmpty = true; + return "$" + (c.MemberName = "Column" + n); + }) + }, + ResultException = p.ResultException, + SimilarTables = p.SimilarTables == null ? new List<Table>() : + p.SimilarTables + .Select(t => tables.Single(tbl => tbl.t == t).table) + .ToList(), + ProcParameters = p.Parameters + .Select(pr => new Parameter + { + SchemaName = pr.SchemaName, + SchemaType = pr.SchemaType, + IsIn = pr.IsIn, + IsOut = pr.IsOut, + IsResult = pr.IsResult, + Size = pr.Size, + ParameterName = pr.ParameterName, + ParameterType = pr.ParameterType, + SystemType = pr.SystemType, + DataType = pr.DataType.ToString(), + }) + .ToList(), + } + }) + .ToList(); + + foreach (var p in procedures) + { + if (ReplaceSimilarTables) + if (p.proc.SimilarTables.Count() == 1 || p.proc.SimilarTables.Count(t => !t.IsView) == 1) + p.proc.ResultTable = p.proc.SimilarTables.Count() == 1 ? + p.proc.SimilarTables[0] : + p.proc.SimilarTables.First(t => !t.IsView); + + Procedures[p.key] = p.proc; + } +} + +Dictionary<string,TR> ToDictionary<T,TR>(IEnumerable<T> source, Func<T,string> keyGetter, Func<T,TR> objGetter, Func<TR,int,string> getKeyName) +{ + var dic = new Dictionary<string,TR>(); + var current = 1; + + foreach (var item in source) + { + var key = keyGetter(item); + var obj = objGetter(item); + + if (string.IsNullOrEmpty(key) || dic.ContainsKey(key)) + key = getKeyName(obj, current); + + dic.Add(key, obj); + + current++; + } + + return dic; +} + +string CheckType(Type type, string typeName) +{ + if (!Model.Usings.Contains(type.Namespace)) + Model.Usings.Add(type.Namespace); + return typeName; +} + +void LoadMetadata(DataConnection dataConnection) +{ + if (DataContextObject == null) + { + DataContextObject = new Class(DataContextName) { BaseClass = BaseDataContextClass, }; + + Model.Types.Add(DataContextObject); + } + + LoadServerMetadata(dataConnection); + + if (Tables.Values.SelectMany(_ => _.ForeignKeys.Values).Any(_ => _.AssociationType == AssociationType.OneToMany)) + Model.Usings.Add("System.Collections.Generic"); + + var keyWords = new HashSet<string> + { + "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" + }; + + foreach (var t in Tables.Values) + { + if (keyWords.Contains(t.TypeName)) + t.TypeName = "@" + t.TypeName; + + if (keyWords.Contains(t.DataContextPropertyName)) + t.DataContextPropertyName = "@" + t.DataContextPropertyName; + + foreach (var col in t.Columns.Values) + if (keyWords.Contains(col.MemberName)) + col.MemberName = "@" + col.MemberName; + } +} + +Table GetTable(string name) +{ + Table tbl; + + if (Tables.TryGetValue(name, out tbl)) + return tbl; + + WriteLine("#error Table '" + name + "' not found."); + WriteLine("/*"); + WriteLine("\tExisting tables:"); + WriteLine(""); + + foreach (var key in Tables.Keys) + WriteLine("\t" + key); + + WriteLine(" */"); + + throw new ArgumentException("Table '" + name + "' not found."); +} + +Procedure GetProcedure(string name) +{ + Procedure proc; + + if (Procedures.TryGetValue(name, out proc)) + return proc; + + WriteLine("#error Procedure '" + name + "' not found."); + WriteLine(""); + WriteLine("/*"); + WriteLine("\tExisting procedures:"); + WriteLine(""); + + foreach (var key in Procedures.Keys) + WriteLine("\t" + key); + + WriteLine(" */"); + + throw new ArgumentException("Procedure '" + name + "' not found."); +} + +Column GetColumn(string tableName, string columnName) +{ + var tbl = GetTable(tableName); + + Column col; + + if (tbl.Columns.TryGetValue(columnName, out col)) + return col; + + WriteLine("#error Column '" + tableName + "'.'" + columnName + "' not found."); + WriteLine(""); + WriteLine("/*"); + WriteLine("\tExisting '" + tableName + "'columns:"); + WriteLine(""); + + foreach (var key in tbl.Columns.Keys) + WriteLine("\t" + key); + + WriteLine(" */"); + + throw new ArgumentException("Column '" + tableName + "'.'" + columnName + "' not found."); +} + +ForeignKey GetFK(string tableName, string fkName) +{ + return GetForeignKey(tableName, fkName); +} + +ForeignKey GetForeignKey(string tableName, string fkName) +{ + var tbl = GetTable(tableName); + + ForeignKey col; + + if (tbl.ForeignKeys.TryGetValue(fkName, out col)) + return col; + + WriteLine("#error FK '" + tableName + "'.'" + fkName + "' not found."); + WriteLine(""); + WriteLine("/*"); + WriteLine("\tExisting '" + tableName + "'FKs:"); + WriteLine(""); + + foreach (var key in tbl.ForeignKeys.Keys) + WriteLine("\t" + key); + + WriteLine(" */"); + + throw new ArgumentException("FK '" + tableName + "'.'" + fkName + "' not found."); +} + + +Dictionary<string,Table> Tables = new Dictionary<string,Table> (); +Dictionary<string,Procedure> Procedures = new Dictionary<string,Procedure>(); + +public partial class Table : Class +{ + public string Schema { get; set; } + public string TableName { get; set; } + public string DataContextPropertyName { get; set; } + public bool IsView { get; set; } + public string Description { get; set; } + public string AliasPropertyName { get; set; } + public string AliasTypeName { get; set; } + + public string TypeName + { + get { return Name; } + set { Name = value; } + } + + public Dictionary<string,Column> Columns; + public Dictionary<string,ForeignKey> ForeignKeys = new Dictionary<string,ForeignKey>(); +} + +public partial class Column : Property +{ + public string ColumnName; // Column name in database + public bool IsNullable; + public bool IsIdentity; + public string ColumnType; // Type of the column in database + public DbType DbType; + public string Description; + public bool IsPrimaryKey; + public int PrimaryKeyOrder; + public bool SkipOnUpdate; + public bool SkipOnInsert; + public bool IsDuplicateOrEmpty; + public string AliasName; + + public string MemberName + { + get { return Name; } + set { Name = value; } + } +} + +public enum AssociationType +{ + Auto, + OneToOne, + OneToMany, + ManyToOne, +} + +public partial class ForeignKey : Property +{ + public string KeyName; + public Table OtherTable; + public List<Column> ThisColumns; + public List<Column> OtherColumns; + public bool CanBeNull; + public ForeignKey BackReference; + + public string MemberName + { + get { return Name; } + set { Name = value; } + } + + private AssociationType _associationType = AssociationType.Auto; + public AssociationType AssociationType + { + get { return _associationType; } + set + { + _associationType = value; + + if (BackReference != null) + { + switch (value) + { + case AssociationType.Auto : BackReference.AssociationType = AssociationType.Auto; break; + case AssociationType.OneToOne : BackReference.AssociationType = AssociationType.OneToOne; break; + case AssociationType.OneToMany : BackReference.AssociationType = AssociationType.ManyToOne; break; + case AssociationType.ManyToOne : BackReference.AssociationType = AssociationType.OneToMany; break; + } + } + } + } +} + +public partial class Procedure : Method +{ + public string Schema { get; set; } + public string ProcedureName { get; set; } + public bool IsFunction { get; set; } + public bool IsTableFunction { get; set; } + public bool IsDefaultSchema { get; set; } + + public Table ResultTable { get; set; } + public Exception ResultException { get; set; } + public List<Table> SimilarTables { get; set; } + public List<Parameter> ProcParameters { get; set; } +} + +public class Parameter +{ + public string SchemaName { get; set; } + public string SchemaType { get; set; } + public bool IsIn { get; set; } + public bool IsOut { get; set; } + public bool IsResult { get; set; } + public int? Size { get; set; } + + public string ParameterName { get; set; } + public string ParameterType { get; set; } + public Type SystemType { get; set; } + public string DataType { get; set; } +} + +#> |