| 
0
 | 
     1 <#@ assembly name="System.Core"    #>
 | 
| 
 | 
     2 <#@ assembly name="System.Data"    #>
 | 
| 
 | 
     3 <#@ import namespace="System.Collections.Generic" #>
 | 
| 
 | 
     4 <#@ import namespace="System.Data" #>
 | 
| 
 | 
     5 <#@ import namespace="System.Linq" #>
 | 
| 
 | 
     6 <#@ import namespace="System.IO"   #>
 | 
| 
 | 
     7 <#
 | 
| 
 | 
     8 	AppDomain.CurrentDomain.AssemblyResolve += (_,args) =>
 | 
| 
 | 
     9 	{
 | 
| 
 | 
    10 		foreach (var a in Assemblies)
 | 
| 
 | 
    11 			if (args.Name.ToLower().IndexOf(a.Key.ToLower()) >= 0)
 | 
| 
 | 
    12 				return System.Reflection.Assembly.LoadFile(a.Value);
 | 
| 
 | 
    13 	
 | 
| 
 | 
    14 		if (DataProviderAssembly != null && args.Name.Split(',')[0] == System.IO.Path.GetFileNameWithoutExtension(DataProviderAssembly))
 | 
| 
 | 
    15 			return System.Reflection.Assembly.LoadFile(DataProviderAssembly);
 | 
| 
 | 
    16 
 | 
| 
 | 
    17 		return null;
 | 
| 
 | 
    18 	};
 | 
| 
 | 
    19 #><#+
 | 
| 
 | 
    20 
 | 
| 
 | 
    21 static Dictionary<string,string> Assemblies = new Dictionary<string,string>();
 | 
| 
 | 
    22 
 | 
| 
 | 
    23 static Action<GeneratedTextTransformation,string> WriteComment        = (tt,s) => tt.WriteLine("//{0}", s);
 | 
| 
 | 
    24 static Action<GeneratedTextTransformation,string> WriteSummary        = (tt,s) => 
 | 
| 
 | 
    25 {
 | 
| 
 | 
    26 	if (!string.IsNullOrWhiteSpace(s))
 | 
| 
 | 
    27 	{
 | 
| 
 | 
    28 		tt.WriteLine("/// <summary>");
 | 
| 
 | 
    29 		tt.WriteLine("/// {0}", s);
 | 
| 
 | 
    30 		tt.WriteLine("/// </summary>");
 | 
| 
 | 
    31 	}
 | 
| 
 | 
    32 };
 | 
| 
 | 
    33 static Action<GeneratedTextTransformation,string> WriteUsing          = (tt,s) => tt.WriteLine("using {0};", s);
 | 
| 
 | 
    34 static Action<GeneratedTextTransformation,string> WriteBeginNamespace = (tt,s) => { tt.WriteLine("namespace {0}", s); tt.WriteLine("{"); };
 | 
| 
 | 
    35 static Action<GeneratedTextTransformation>        WriteEndNamespace   =  tt    => tt.WriteLine("}");
 | 
| 
 | 
    36 static Action<GeneratedTextTransformation,string,string> WriteBeginClass = (tt,cl,bc) =>
 | 
| 
 | 
    37 {
 | 
| 
 | 
    38 	tt.Write("public partial class {0}", cl);
 | 
| 
 | 
    39 	if (!string.IsNullOrEmpty(bc))
 | 
| 
 | 
    40 		tt.Write(" : {0}", bc);
 | 
| 
 | 
    41 	tt.WriteLine("");
 | 
| 
 | 
    42 	tt.WriteLine("{");
 | 
| 
 | 
    43 };
 | 
| 
 | 
    44 static Action<GeneratedTextTransformation>        WriteEndClass       =  tt   => tt.WriteLine("}");
 | 
| 
 | 
    45 static Func<string,string,string>                 MakeGenericType     = (c,t) => string.Format("{0}<{1}>", c, t);
 | 
| 
 | 
    46 static Func<string,string>                        MakeType            = t     => t;
 | 
| 
 | 
    47 
 | 
| 
 | 
    48 delegate void WriteTablePropertyAction(GeneratedTextTransformation tt, string name, string pname, int maxlen, int maxplen, string desc);
 | 
| 
 | 
    49 
 | 
| 
 | 
    50 static WriteTablePropertyAction WriteTableProperty = (tt,name,pname,maxlen,maxplen,desc) =>
 | 
| 
 | 
    51 {
 | 
| 
 | 
    52 	WriteSummary(tt,desc);
 | 
| 
 | 
    53 	tt.WriteLine("public Table<{0}>{1} {2}{3} {{ get {{ return this.GetTable<{0}>();{1} }} }}", name, tt.LenDiff(maxlen, name), pname, tt.LenDiff(maxplen, pname));
 | 
| 
 | 
    54 };
 | 
| 
 | 
    55 static Action<GeneratedTextTransformation,string> WriteAttribute      = (tt,a) => tt.Write("[{0}]", a);
 | 
| 
 | 
    56 static Action<GeneratedTextTransformation>        WriteAttributeLine  =  tt    => tt.WriteLine("");
 | 
| 
 | 
    57 
 | 
| 
 | 
    58 static string ConnectionString;
 | 
| 
 | 
    59 static string ConnectionType;
 | 
| 
 | 
    60 static string DataProviderAssembly = null;
 | 
| 
 | 
    61 
 | 
| 
 | 
    62 string DatabaseName             = null;
 | 
| 
 | 
    63 string DataContextName          = null;
 | 
| 
 | 
    64 string Namespace                = "DataModel";
 | 
| 
 | 
    65 string BaseDataContextClass     = "DbManager";
 | 
| 
 | 
    66 string BaseEntityClass          = null;
 | 
| 
 | 
    67 string OneToManyAssociationType = "IEnumerable<{0}>";
 | 
| 
 | 
    68 
 | 
| 
 | 
    69 string OwnerToInclude           = null;
 | 
| 
 | 
    70 string[] DatabaseQuote          = null;
 | 
| 
 | 
    71 
 | 
| 
 | 
    72 bool   RenderField              = false;
 | 
| 
 | 
    73 bool   RenderBackReferences     = true;
 | 
| 
 | 
    74 bool   RenderForeignKeys        = true;
 | 
| 
 | 
    75 
 | 
| 
 | 
    76 bool   IsMetadataLoaded;
 | 
| 
 | 
    77 
 | 
| 
 | 
    78 int MaxColumnTypeLen;
 | 
| 
 | 
    79 int MaxColumnMemberLen;
 | 
| 
 | 
    80 
 | 
| 
 | 
    81 static Action<GeneratedTextTransformation,Column,int[],string[]> RenderColumn = (tt,c,maxLens,attrs) =>
 | 
| 
 | 
    82 {
 | 
| 
 | 
    83 	WriteSummary(tt,c.Description);
 | 
| 
 | 
    84 	
 | 
| 
 | 
    85 	if (maxLens.Sum() > 0)
 | 
| 
 | 
    86 	{
 | 
| 
 | 
    87 		if (attrs.Any(_ => _ != null))
 | 
| 
 | 
    88 		{
 | 
| 
 | 
    89 			tt.Write("[");
 | 
| 
 | 
    90 
 | 
| 
 | 
    91 			for (var i = 0; i < attrs.Length; i++)
 | 
| 
 | 
    92 			{
 | 
| 
 | 
    93 				if (attrs[i] != null)
 | 
| 
 | 
    94 				{
 | 
| 
 | 
    95 					tt.Write(attrs[i]);
 | 
| 
 | 
    96 					tt.WriteSpace(maxLens[i] - attrs[i].Length);
 | 
| 
 | 
    97 
 | 
| 
 | 
    98 					if (attrs.Skip(i + 1).Any(_ => _ != null))
 | 
| 
 | 
    99 						tt.Write(", ");
 | 
| 
 | 
   100 					else if (maxLens.Skip(i + 1).Any(_ => _ > 0))
 | 
| 
 | 
   101 						tt.WriteSpace(2);
 | 
| 
 | 
   102 				}
 | 
| 
 | 
   103 				else if (maxLens[i] > 0)
 | 
| 
 | 
   104 				{
 | 
| 
 | 
   105 					tt.WriteSpace(maxLens[i]);
 | 
| 
 | 
   106 					
 | 
| 
 | 
   107 					if (maxLens.Skip(i + 1).Any(_ => _ > 0))
 | 
| 
 | 
   108 						tt.WriteSpace(2);
 | 
| 
 | 
   109 				}
 | 
| 
 | 
   110 			}
 | 
| 
 | 
   111 
 | 
| 
 | 
   112 			tt.Write("] ");
 | 
| 
 | 
   113 		}
 | 
| 
 | 
   114 		else
 | 
| 
 | 
   115 		{
 | 
| 
 | 
   116 			tt.WriteSpace(maxLens.Sum() + (maxLens.Where(_ => _ > 0).Count() - 1) * 2 + 3);
 | 
| 
 | 
   117 		}
 | 
| 
 | 
   118 	}
 | 
| 
 | 
   119 
 | 
| 
 | 
   120 	tt.Write("public {0}{1} {2}", c.Type, tt.LenDiff(tt.MaxColumnTypeLen, c.Type), c.MemberName);
 | 
| 
 | 
   121 
 | 
| 
 | 
   122 	if (tt.RenderField)
 | 
| 
 | 
   123 	{
 | 
| 
 | 
   124 		tt.Write(";");
 | 
| 
 | 
   125 		if (c.ColumnType != null)
 | 
| 
 | 
   126 			tt.Write(tt.LenDiff(tt.MaxColumnMemberLen, c.MemberName));
 | 
| 
 | 
   127 	}
 | 
| 
 | 
   128 	else
 | 
| 
 | 
   129 		tt.Write("{0} {{ get; set; }}", tt.LenDiff(tt.MaxColumnMemberLen, c.MemberName));
 | 
| 
 | 
   130 
 | 
| 
 | 
   131 	if (c.ColumnType != null)
 | 
| 
 | 
   132 	{
 | 
| 
 | 
   133 		tt.Write(" // {0}", c.ColumnType);
 | 
| 
 | 
   134 		
 | 
| 
 | 
   135 		if (c.Length != 0)
 | 
| 
 | 
   136 			tt.Write("({0})", c.Length);
 | 
| 
 | 
   137 
 | 
| 
 | 
   138 		if (c.Precision != 0)
 | 
| 
 | 
   139 		{
 | 
| 
 | 
   140 			if (c.Scale == 0)
 | 
| 
 | 
   141 				tt.Write("({0})", c.Precision);
 | 
| 
 | 
   142 			else
 | 
| 
 | 
   143 				tt.Write("({0},{1})", c.Precision, c.Scale);
 | 
| 
 | 
   144 		}
 | 
| 
 | 
   145 	}
 | 
| 
 | 
   146 
 | 
| 
 | 
   147 	tt.WriteLine("");
 | 
| 
 | 
   148 };
 | 
| 
 | 
   149 
 | 
| 
 | 
   150 static Action<GeneratedTextTransformation,ForeignKey> RenderForeignKey = (tt,key) =>
 | 
| 
 | 
   151 {
 | 
| 
 | 
   152 	WriteComment(tt, " " + key.KeyName);
 | 
| 
 | 
   153 	tt.WriteLine("[Association(ThisKey=\"{0}\", OtherKey=\"{1}\", CanBeNull={2})]",
 | 
| 
 | 
   154 		string.Join(", ", (from c in key.ThisColumns  select c.MemberName).ToArray()),
 | 
| 
 | 
   155 		string.Join(", ", (from c in key.OtherColumns select c.MemberName).ToArray()),
 | 
| 
 | 
   156 		key.CanBeNull ? "true" : "false");
 | 
| 
 | 
   157 
 | 
| 
 | 
   158 	if (key.Attributes.Count > 0)
 | 
| 
 | 
   159 	{
 | 
| 
 | 
   160 		WriteAttribute(tt, string.Join(", ", key.Attributes.Distinct().ToArray()));
 | 
| 
 | 
   161 		WriteAttributeLine(tt);
 | 
| 
 | 
   162 	}
 | 
| 
 | 
   163 
 | 
| 
 | 
   164 	tt.Write("public ");
 | 
| 
 | 
   165 
 | 
| 
 | 
   166 	if (key.AssociationType == AssociationType.OneToMany)
 | 
| 
 | 
   167 		tt.Write(tt.OneToManyAssociationType, key.OtherTable.ClassName);
 | 
| 
 | 
   168 	else
 | 
| 
 | 
   169 		tt.Write(key.OtherTable.ClassName);
 | 
| 
 | 
   170 
 | 
| 
 | 
   171 	tt.Write(" ");
 | 
| 
 | 
   172 	tt.Write(key.MemberName);
 | 
| 
 | 
   173 
 | 
| 
 | 
   174 	if (tt.RenderField)
 | 
| 
 | 
   175 		tt.WriteLine(";");
 | 
| 
 | 
   176 	else
 | 
| 
 | 
   177 		tt.WriteLine(" { get; set; }");
 | 
| 
 | 
   178 };
 | 
| 
 | 
   179 
 | 
| 
 | 
   180 static Action<GeneratedTextTransformation,Table, bool> RenderTable = (tt,t, renderForeignKeys) =>
 | 
| 
 | 
   181 {
 | 
| 
 | 
   182 	WriteSummary(tt,t.Description);
 | 
| 
 | 
   183 
 | 
| 
 | 
   184 	if (t.IsView)
 | 
| 
 | 
   185 	{
 | 
| 
 | 
   186 		WriteComment(tt, " View");
 | 
| 
 | 
   187 	}
 | 
| 
 | 
   188 
 | 
| 
 | 
   189 	RenderTableAttributes(tt, t);
 | 
| 
 | 
   190 
 | 
| 
 | 
   191 	WriteBeginClass(tt, t.ClassName, t.BaseClassName);
 | 
| 
 | 
   192 	
 | 
| 
 | 
   193 	tt.PushIndent("\t");
 | 
| 
 | 
   194 
 | 
| 
 | 
   195 	if (t.Columns.Count > 0)
 | 
| 
 | 
   196 	{
 | 
| 
 | 
   197 		tt.MaxColumnTypeLen   = t.Columns.Values.Max(_ => _.Type.Length);
 | 
| 
 | 
   198 		tt.MaxColumnMemberLen = t.Columns.Values.Max(_ => _.MemberName.Length);
 | 
| 
 | 
   199 
 | 
| 
 | 
   200 		var maxLens = new int[]
 | 
| 
 | 
   201 		{
 | 
| 
 | 
   202 			t.Columns.Values.Max(_ => _.MemberName == _.ColumnName ? 0 : "MapField('')".Length + _.ColumnName.Length),
 | 
| 
 | 
   203 			t.Columns.Values.Max(_ => _.IsNullable                 ? "Nullable".Length : _.IsIdentity ? "Identity".Length : 0),
 | 
| 
 | 
   204 			t.Columns.Values.Max(_ => _.IsIdentity && _.IsNullable ? "Identity".Length : 0),
 | 
| 
 | 
   205 			t.Columns.Values.Max(_ => _.IsPrimaryKey               ? string.Format("PrimaryKey({0})", _.PKIndex).Length : 0),
 | 
| 
 | 
   206 			t.Columns.Values.Max(_ => _.Attributes.Count == 0      ? 0 : string.Join(", ", _.Attributes.Distinct().ToArray()).Length),
 | 
| 
 | 
   207 		};
 | 
| 
 | 
   208 
 | 
| 
 | 
   209 		foreach (var c in from c in t.Columns.Values orderby c.ID select c)
 | 
| 
 | 
   210 		{
 | 
| 
 | 
   211 			var attrs = new string[]
 | 
| 
 | 
   212 			{
 | 
| 
 | 
   213 				c.MemberName == c.ColumnName ? null : string.Format("MapField(\"{0}\")", c.ColumnName),
 | 
| 
 | 
   214 				c.IsNullable                 ? "Nullable" : c.IsIdentity ? "Identity" : null,
 | 
| 
 | 
   215 				c.IsIdentity && c.IsNullable ? "Identity" : null,
 | 
| 
 | 
   216 				c.IsPrimaryKey               ? string.Format("PrimaryKey({0})", c.PKIndex) : null,
 | 
| 
 | 
   217 				c.Attributes.Count == 0      ? null : string.Join(", ", c.Attributes.Distinct().ToArray()),
 | 
| 
 | 
   218 			};
 | 
| 
 | 
   219 
 | 
| 
 | 
   220 			RenderColumn(tt, c, maxLens, attrs);
 | 
| 
 | 
   221 		}
 | 
| 
 | 
   222 	}
 | 
| 
 | 
   223 
 | 
| 
 | 
   224 	if (renderForeignKeys && t.ForeignKeys.Count > 0)
 | 
| 
 | 
   225 	{
 | 
| 
 | 
   226 		foreach (var key in t.ForeignKeys.Values.Where(k => tt.RenderBackReferences || k.BackReference != null))
 | 
| 
 | 
   227 		{
 | 
| 
 | 
   228 			tt.WriteLine("");
 | 
| 
 | 
   229 			RenderForeignKey(tt, key);
 | 
| 
 | 
   230 		}
 | 
| 
 | 
   231 	}
 | 
| 
 | 
   232 
 | 
| 
 | 
   233 	tt.PopIndent();
 | 
| 
 | 
   234 	WriteEndClass(tt);
 | 
| 
 | 
   235 };
 | 
| 
 | 
   236 
 | 
| 
 | 
   237 static Action<GeneratedTextTransformation,Table> RenderTableAttributes = (tt,t) =>
 | 
| 
 | 
   238 {
 | 
| 
 | 
   239 	if (t.Attributes.Count > 0)
 | 
| 
 | 
   240 	{
 | 
| 
 | 
   241 		WriteAttribute(tt, string.Join(", ", t.Attributes.Distinct().ToArray()));
 | 
| 
 | 
   242 		WriteAttributeLine(tt);
 | 
| 
 | 
   243 	}
 | 
| 
 | 
   244 
 | 
| 
 | 
   245 	string tbl = "TableName(";
 | 
| 
 | 
   246 
 | 
| 
 | 
   247 	if (!string.IsNullOrEmpty(tt.DatabaseName))
 | 
| 
 | 
   248 		tbl += string.Format("Database=\"{0}\", ", tt.DatabaseName);
 | 
| 
 | 
   249 
 | 
| 
 | 
   250 	if (!string.IsNullOrEmpty(t.Owner))
 | 
| 
 | 
   251 		tbl += string.Format("Owner=\"{0}\", ", t.Owner);
 | 
| 
 | 
   252 
 | 
| 
 | 
   253 	tbl += string.Format("Name=\"{0}\")", t.TableName);
 | 
| 
 | 
   254 
 | 
| 
 | 
   255 	WriteAttribute(tt, tbl);
 | 
| 
 | 
   256 	WriteAttributeLine(tt);
 | 
| 
 | 
   257 };
 | 
| 
 | 
   258 
 | 
| 
 | 
   259 List<string> Usings = new List<string>()
 | 
| 
 | 
   260 {
 | 
| 
 | 
   261 	"System",
 | 
| 
 | 
   262 	"BLToolkit.Data",
 | 
| 
 | 
   263 	"BLToolkit.Data.Linq",
 | 
| 
 | 
   264 	"BLToolkit.DataAccess",
 | 
| 
 | 
   265 	"BLToolkit.Mapping",
 | 
| 
 | 
   266 };
 | 
| 
 | 
   267 
 | 
| 
 | 
   268 static Action<GeneratedTextTransformation> RenderUsing = tt =>
 | 
| 
 | 
   269 {
 | 
| 
 | 
   270 	var q =
 | 
| 
 | 
   271 		from ns in tt.Usings.Distinct()
 | 
| 
 | 
   272 		group ns by ns.Split('.')[0];
 | 
| 
 | 
   273 
 | 
| 
 | 
   274 	var groups =
 | 
| 
 | 
   275 		(from ns in q where ns.Key == "System"                select ns).Concat
 | 
| 
 | 
   276 		(from ns in q where ns.Key != "System" orderby ns.Key select ns);
 | 
| 
 | 
   277 
 | 
| 
 | 
   278 	foreach (var gr in groups)
 | 
| 
 | 
   279 	{
 | 
| 
 | 
   280 		foreach (var ns in from s in gr orderby s select s)
 | 
| 
 | 
   281 			WriteUsing(tt, ns);
 | 
| 
 | 
   282 
 | 
| 
 | 
   283 		tt.WriteLine("");
 | 
| 
 | 
   284 	}
 | 
| 
 | 
   285 };
 | 
| 
 | 
   286 
 | 
| 
 | 
   287 Action<GeneratedTextTransformation> BeforeGenerateModel = _ => {};
 | 
| 
 | 
   288 Action<GeneratedTextTransformation> AfterGenerateModel  = _ => {};
 | 
| 
 | 
   289 
 | 
| 
 | 
   290 Action<GeneratedTextTransformation> BeforeWriteTableProperty = _ => {};
 | 
| 
 | 
   291 Action<GeneratedTextTransformation> AfterWriteTableProperty  = _ => {};
 | 
| 
 | 
   292 
 | 
| 
 | 
   293 void GenerateModel()
 | 
| 
 | 
   294 {
 | 
| 
 | 
   295 	if (ConnectionString != null) ConnectionString = ConnectionString.Trim();
 | 
| 
 | 
   296 	if (DataContextName  != null) DataContextName  = DataContextName. Trim();
 | 
| 
 | 
   297 
 | 
| 
 | 
   298 	if (string.IsNullOrEmpty(ConnectionString)) { Error("ConnectionString cannot be empty."); return; }
 | 
| 
 | 
   299 
 | 
| 
 | 
   300 	if (string.IsNullOrEmpty(DataContextName))
 | 
| 
 | 
   301 		DataContextName = "DataContext";
 | 
| 
 | 
   302 
 | 
| 
 | 
   303 	LoadMetadata();
 | 
| 
 | 
   304 
 | 
| 
 | 
   305 	BeforeGenerateModel(this);
 | 
| 
 | 
   306 
 | 
| 
 | 
   307 	WriteComment(this, "---------------------------------------------------------------------------------------------------");
 | 
| 
 | 
   308 	WriteComment(this, " <auto-generated>");
 | 
| 
 | 
   309 	WriteComment(this, "    This code was generated by BLToolkit template for T4.");
 | 
| 
 | 
   310 	WriteComment(this, "    Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.");
 | 
| 
 | 
   311 	WriteComment(this, " </auto-generated>");
 | 
| 
 | 
   312 	WriteComment(this, "---------------------------------------------------------------------------------------------------");
 | 
| 
 | 
   313 
 | 
| 
 | 
   314 	RenderUsing(this);
 | 
| 
 | 
   315 
 | 
| 
 | 
   316 	WriteBeginNamespace(this, Namespace);
 | 
| 
 | 
   317 	PushIndent("\t");
 | 
| 
 | 
   318 
 | 
| 
 | 
   319 	WriteBeginClass(this, DataContextName, BaseDataContextClass);
 | 
| 
 | 
   320 
 | 
| 
 | 
   321 	var tlist   = (from t in Tables.Values orderby t.TableName select t).ToList();
 | 
| 
 | 
   322 	var maxlen  = tlist.Max(_ => _.ClassName.Length);
 | 
| 
 | 
   323 	var maxplen = tlist.Max(_ => (_.DataContextPropertyName ?? _.ClassName).Length);
 | 
| 
 | 
   324 
 | 
| 
 | 
   325 	PushIndent("\t");
 | 
| 
 | 
   326 
 | 
| 
 | 
   327 	BeforeWriteTableProperty(this);
 | 
| 
 | 
   328 
 | 
| 
 | 
   329 	foreach (var t in tlist)
 | 
| 
 | 
   330 		WriteTableProperty(this, t.ClassName, t.DataContextPropertyName ?? t.ClassName, maxlen, maxplen, t.Description);
 | 
| 
 | 
   331 
 | 
| 
 | 
   332 	AfterWriteTableProperty(this);
 | 
| 
 | 
   333 
 | 
| 
 | 
   334 	PopIndent();
 | 
| 
 | 
   335 
 | 
| 
 | 
   336 	WriteEndClass(this);
 | 
| 
 | 
   337 
 | 
| 
 | 
   338 	foreach (var t in tlist)
 | 
| 
 | 
   339 	{
 | 
| 
 | 
   340 		WriteLine("");
 | 
| 
 | 
   341 		RenderTable(this, t, RenderForeignKeys);
 | 
| 
 | 
   342 	}
 | 
| 
 | 
   343 
 | 
| 
 | 
   344 	PopIndent();
 | 
| 
 | 
   345 	WriteEndNamespace(this);
 | 
| 
 | 
   346 
 | 
| 
 | 
   347 	AfterGenerateModel(this);
 | 
| 
 | 
   348 }
 | 
| 
 | 
   349 
 | 
| 
 | 
   350 string LenDiff(int max, string str)
 | 
| 
 | 
   351 {
 | 
| 
 | 
   352 	var s = "";
 | 
| 
 | 
   353 
 | 
| 
 | 
   354 	while (max-- > str.Length)
 | 
| 
 | 
   355 		s += " ";
 | 
| 
 | 
   356 
 | 
| 
 | 
   357 	return s;
 | 
| 
 | 
   358 }
 | 
| 
 | 
   359 
 | 
| 
 | 
   360 void WriteSpace(int len)
 | 
| 
 | 
   361 {
 | 
| 
 | 
   362 	while (len-- > 0)
 | 
| 
 | 
   363 		Write(" ");
 | 
| 
 | 
   364 }
 | 
| 
 | 
   365 
 | 
| 
 | 
   366 List<T> CreateList<T>(T item)
 | 
| 
 | 
   367 {
 | 
| 
 | 
   368 	return new List<T>();
 | 
| 
 | 
   369 }
 | 
| 
 | 
   370 
 | 
| 
 | 
   371 Func<System.Data.IDbConnection> GetConnectionObject = () =>
 | 
| 
 | 
   372 {
 | 
| 
 | 
   373 	Type connType = null;
 | 
| 
 | 
   374 
 | 
| 
 | 
   375 	if (DataProviderAssembly != null)
 | 
| 
 | 
   376 	{
 | 
| 
 | 
   377 		try
 | 
| 
 | 
   378 		{
 | 
| 
 | 
   379 			var assembly = System.Reflection.Assembly.LoadFile(DataProviderAssembly);
 | 
| 
 | 
   380 			connType = assembly.GetType(ConnectionType) 
 | 
| 
 | 
   381 				?? assembly.GetType(ConnectionType.Substring(0, ConnectionType.IndexOf(",")));
 | 
| 
 | 
   382 		}
 | 
| 
 | 
   383 		catch
 | 
| 
 | 
   384 		{
 | 
| 
 | 
   385 		}
 | 
| 
 | 
   386 	}
 | 
| 
 | 
   387 
 | 
| 
 | 
   388 	if (connType == null)
 | 
| 
 | 
   389 		connType = Type.GetType(ConnectionType);
 | 
| 
 | 
   390 
 | 
| 
 | 
   391 	return (System.Data.IDbConnection)Activator.CreateInstance(connType);
 | 
| 
 | 
   392 };
 | 
| 
 | 
   393 
 | 
| 
 | 
   394 System.Data.IDbConnection GetConnection()
 | 
| 
 | 
   395 {
 | 
| 
 | 
   396 	var conn = GetConnectionObject();
 | 
| 
 | 
   397 
 | 
| 
 | 
   398 	conn.ConnectionString = ConnectionString;
 | 
| 
 | 
   399 	conn.Open();
 | 
| 
 | 
   400 
 | 
| 
 | 
   401 	return conn;
 | 
| 
 | 
   402 }
 | 
| 
 | 
   403 
 | 
| 
 | 
   404 void LoadMetadata()
 | 
| 
 | 
   405 {
 | 
| 
 | 
   406 	if (IsMetadataLoaded)
 | 
| 
 | 
   407 		return;
 | 
| 
 | 
   408 
 | 
| 
 | 
   409 	IsMetadataLoaded = true;
 | 
| 
 | 
   410 
 | 
| 
 | 
   411 	if (!string.IsNullOrEmpty(DataProviderAssembly) && !DataProviderAssembly.Contains(":") && DataProviderAssembly.Contains(".."))
 | 
| 
 | 
   412 	{
 | 
| 
 | 
   413 		try
 | 
| 
 | 
   414 		{
 | 
| 
 | 
   415 			string path = this.Host.ResolvePath("");
 | 
| 
 | 
   416 			DataProviderAssembly = Path.GetFullPath(Path.Combine(path, DataProviderAssembly));
 | 
| 
 | 
   417 		}
 | 
| 
 | 
   418 		catch 
 | 
| 
 | 
   419 		{
 | 
| 
 | 
   420 		}
 | 
| 
 | 
   421 	}
 | 
| 
 | 
   422 
 | 
| 
 | 
   423 	BeforeLoadMetadata(this);
 | 
| 
 | 
   424 	LoadServerMetadata();
 | 
| 
 | 
   425 
 | 
| 
 | 
   426 	if (DatabaseQuote != null)
 | 
| 
 | 
   427 	{
 | 
| 
 | 
   428 		foreach (var t in Tables.Values)
 | 
| 
 | 
   429 		{
 | 
| 
 | 
   430 			t.TableName = string.Format("{1}{0}{2}", t.TableName, DatabaseQuote.FirstOrDefault(), DatabaseQuote.Skip(1).FirstOrDefault() ?? DatabaseQuote.FirstOrDefault());
 | 
| 
 | 
   431 			foreach (var c in t.Columns.Values)
 | 
| 
 | 
   432 			{
 | 
| 
 | 
   433 				c.ColumnName = string.Format("{1}{0}{2}", c.ColumnName, DatabaseQuote.FirstOrDefault(), DatabaseQuote.Skip(1).FirstOrDefault() ?? DatabaseQuote.FirstOrDefault());
 | 
| 
 | 
   434 			}
 | 
| 
 | 
   435 		}
 | 
| 
 | 
   436 	}
 | 
| 
 | 
   437 
 | 
| 
 | 
   438 	foreach (var t in Tables.Values)
 | 
| 
 | 
   439 	{
 | 
| 
 | 
   440 		if (t.ClassName.Contains(" "))
 | 
| 
 | 
   441 		{
 | 
| 
 | 
   442 			var ss = t.ClassName.Split(' ').Where(_ => _.Trim().Length > 0).Select(_ => char.ToUpper(_[0]) + _.Substring(1));
 | 
| 
 | 
   443 			t.ClassName = string.Join("", ss.ToArray());
 | 
| 
 | 
   444 		}
 | 
| 
 | 
   445 	}
 | 
| 
 | 
   446 
 | 
| 
 | 
   447 	foreach (var t in Tables.Values)
 | 
| 
 | 
   448 		foreach (var key in t.ForeignKeys.Values.ToList())
 | 
| 
 | 
   449 			if (!key.KeyName.EndsWith("_BackReference"))
 | 
| 
 | 
   450 				key.OtherTable.ForeignKeys.Add(key.KeyName + "_BackReference", key.BackReference = new ForeignKey
 | 
| 
 | 
   451 				{
 | 
| 
 | 
   452 					KeyName         = key.KeyName    + "_BackReference",
 | 
| 
 | 
   453 					MemberName      = key.MemberName + "_BackReference",
 | 
| 
 | 
   454 					AssociationType = AssociationType.Auto,
 | 
| 
 | 
   455 					OtherTable      = t,
 | 
| 
 | 
   456 					ThisColumns     = key.OtherColumns,
 | 
| 
 | 
   457 					OtherColumns    = key.ThisColumns,
 | 
| 
 | 
   458 				});
 | 
| 
 | 
   459 
 | 
| 
 | 
   460 	foreach (var t in Tables.Values)
 | 
| 
 | 
   461 	{
 | 
| 
 | 
   462 		foreach (var key in t.ForeignKeys.Values)
 | 
| 
 | 
   463 		{
 | 
| 
 | 
   464 			if (key.BackReference != null && key.AssociationType == AssociationType.Auto)
 | 
| 
 | 
   465 			{
 | 
| 
 | 
   466 				if (key.ThisColumns.All(_ => _.IsPrimaryKey))
 | 
| 
 | 
   467 				{
 | 
| 
 | 
   468 					if (t.Columns.Values.Count(_ => _.IsPrimaryKey) == key.ThisColumns.Count)
 | 
| 
 | 
   469 						key.AssociationType = AssociationType.OneToOne;
 | 
| 
 | 
   470 					else
 | 
| 
 | 
   471 						key.AssociationType = AssociationType.ManyToOne;
 | 
| 
 | 
   472 				}
 | 
| 
 | 
   473 				else
 | 
| 
 | 
   474 					key.AssociationType = AssociationType.ManyToOne;
 | 
| 
 | 
   475 
 | 
| 
 | 
   476 				key.CanBeNull = key.ThisColumns.All(_ => _.IsNullable);
 | 
| 
 | 
   477 			}
 | 
| 
 | 
   478 		}
 | 
| 
 | 
   479 	}
 | 
| 
 | 
   480 
 | 
| 
 | 
   481 	foreach (var t in Tables.Values)
 | 
| 
 | 
   482 	{
 | 
| 
 | 
   483 		foreach (var key in t.ForeignKeys.Values)
 | 
| 
 | 
   484 		{
 | 
| 
 | 
   485 			var name = key.MemberName;
 | 
| 
 | 
   486 
 | 
| 
 | 
   487 			if (key.BackReference != null && key.ThisColumns.Count == 1 && key.ThisColumns[0].MemberName.ToLower().EndsWith("id"))
 | 
| 
 | 
   488 			{
 | 
| 
 | 
   489 				name = key.ThisColumns[0].MemberName;
 | 
| 
 | 
   490 				name = name.Substring(0, name.Length - "id".Length);
 | 
| 
 | 
   491 
 | 
| 
 | 
   492 				if (!t.ForeignKeys.Values.Select(_ => _.MemberName).Concat(
 | 
| 
 | 
   493 					 t.Columns.    Values.Select(_ => _.MemberName)).Concat(
 | 
| 
 | 
   494 					 new[] { t.ClassName }).Any(_ => _ == name))
 | 
| 
 | 
   495 				{
 | 
| 
 | 
   496 					name = key.MemberName;;
 | 
| 
 | 
   497 				}
 | 
| 
 | 
   498 			}
 | 
| 
 | 
   499 			
 | 
| 
 | 
   500 			if (name == key.MemberName)
 | 
| 
 | 
   501 			{
 | 
| 
 | 
   502 				if (name.StartsWith("FK_"))
 | 
| 
 | 
   503 					name = name.Substring(3);
 | 
| 
 | 
   504 
 | 
| 
 | 
   505 				if (name.EndsWith("_BackReference"))
 | 
| 
 | 
   506 					name = name.Substring(0, name.Length - "_BackReference".Length);
 | 
| 
 | 
   507 
 | 
| 
 | 
   508 				name = string.Join("", name.Split('_').Where(_ => _.Length > 0 && _ != t.TableName).ToArray());
 | 
| 
 | 
   509 
 | 
| 
 | 
   510 				if (name.Length > 0)
 | 
| 
 | 
   511 					name = key.AssociationType == AssociationType.OneToMany ? PluralizeAssociationName(name) : SingularizeAssociationName(name);
 | 
| 
 | 
   512 			}
 | 
| 
 | 
   513 
 | 
| 
 | 
   514 			if (name.Length != 0 &&
 | 
| 
 | 
   515 				!t.ForeignKeys.Values.Select(_ => _.MemberName).Concat(
 | 
| 
 | 
   516 				 t.Columns.    Values.Select(_ => _.MemberName)).Concat(
 | 
| 
 | 
   517 				 new[] { t.ClassName }).Any(_ => _ == name))
 | 
| 
 | 
   518 			{
 | 
| 
 | 
   519 				key.MemberName = name;
 | 
| 
 | 
   520 			}
 | 
| 
 | 
   521 		}
 | 
| 
 | 
   522 	}
 | 
| 
 | 
   523 
 | 
| 
 | 
   524 	if (Tables.Values.SelectMany(_ => _.ForeignKeys.Values).Any(_ => _.AssociationType == AssociationType.OneToMany))
 | 
| 
 | 
   525 		Usings.Add("System.Collections.Generic");
 | 
| 
 | 
   526 
 | 
| 
 | 
   527 	var keyWords = new HashSet<string>
 | 
| 
 | 
   528 	{
 | 
| 
 | 
   529 		"abstract", "as",       "base",     "bool",    "break",     "byte",     "case",       "catch",     "char",    "checked",
 | 
| 
 | 
   530 		"class",    "const",    "continue", "decimal", "default",   "delegate", "do",         "double",    "else",    "enum",
 | 
| 
 | 
   531 		"event",    "explicit", "extern",   "false",   "finally",   "fixed",    "float",      "for",       "foreach", "goto",
 | 
| 
 | 
   532 		"if",       "implicit", "in",       "int",     "interface", "internal", "is",         "lock",      "long",    "new",
 | 
| 
 | 
   533 		"null",     "object",   "operator", "out",     "override",  "params",   "private",    "protected", "public",  "readonly",
 | 
| 
 | 
   534 		"ref",      "return",   "sbyte",    "sealed",  "short",     "sizeof",   "stackalloc", "static",    "struct",  "switch",
 | 
| 
 | 
   535 		"this",     "throw",    "true",     "try",     "typeof",    "uint",     "ulong",      "unchecked", "unsafe",  "ushort",
 | 
| 
 | 
   536 		"using",    "virtual",  "volatile", "void",    "while"
 | 
| 
 | 
   537 	};
 | 
| 
 | 
   538 
 | 
| 
 | 
   539 	foreach (var t in Tables.Values)
 | 
| 
 | 
   540 	{
 | 
| 
 | 
   541 		if (keyWords.Contains(t.ClassName))
 | 
| 
 | 
   542 			t.ClassName = "@" + t.ClassName;
 | 
| 
 | 
   543 
 | 
| 
 | 
   544 		if (keyWords.Contains(t.DataContextPropertyName))
 | 
| 
 | 
   545 			t.DataContextPropertyName = "@" + t.DataContextPropertyName;
 | 
| 
 | 
   546 
 | 
| 
 | 
   547 		foreach (var col in t.Columns.Values)
 | 
| 
 | 
   548 			if (keyWords.Contains(col.MemberName))
 | 
| 
 | 
   549 				col.MemberName = "@" + col.MemberName;
 | 
| 
 | 
   550 	}
 | 
| 
 | 
   551 
 | 
| 
 | 
   552 
 | 
| 
 | 
   553 	AfterLoadMetadata(this);
 | 
| 
 | 
   554 }
 | 
| 
 | 
   555 
 | 
| 
 | 
   556 Func<string,string> PluralizeAssociationName   = _ => _ + "s";
 | 
| 
 | 
   557 Func<string,string> SingularizeAssociationName = _ => _;
 | 
| 
 | 
   558 
 | 
| 
 | 
   559 Action<GeneratedTextTransformation> BeforeLoadMetadata = _ => {};
 | 
| 
 | 
   560 Action<GeneratedTextTransformation> AfterLoadMetadata  = _ => {};
 | 
| 
 | 
   561 
 | 
| 
 | 
   562 Dictionary<string,Table> Tables = new Dictionary<string,Table>();
 | 
| 
 | 
   563 
 | 
| 
 | 
   564 public partial class Table
 | 
| 
 | 
   565 {
 | 
| 
 | 
   566 	public string       Owner;
 | 
| 
 | 
   567 	public string       TableName;
 | 
| 
 | 
   568 	public string       ClassName;
 | 
| 
 | 
   569 	public string       DataContextPropertyName;
 | 
| 
 | 
   570 	public string       BaseClassName;
 | 
| 
 | 
   571 	public bool         IsView;
 | 
| 
 | 
   572 	public string		Description;
 | 
| 
 | 
   573 	public List<string> Attributes = new List<string>();
 | 
| 
 | 
   574 
 | 
| 
 | 
   575 	public Dictionary<string,Column>     Columns     = new Dictionary<string,Column>();
 | 
| 
 | 
   576 	public Dictionary<string,ForeignKey> ForeignKeys = new Dictionary<string,ForeignKey>();
 | 
| 
 | 
   577 }
 | 
| 
 | 
   578 
 | 
| 
 | 
   579 public partial class Column
 | 
| 
 | 
   580 {
 | 
| 
 | 
   581 	public int          ID;
 | 
| 
 | 
   582 	public string       ColumnName; // Column name in database
 | 
| 
 | 
   583 	public string       MemberName; // Member name of the generated class
 | 
| 
 | 
   584 	public bool         IsNullable;
 | 
| 
 | 
   585 	public bool         IsIdentity;
 | 
| 
 | 
   586 	public string       Type;       // Type of the generated member
 | 
| 
 | 
   587 	public string       ColumnType; // Type of the column in database
 | 
| 
 | 
   588 	public bool         IsClass;
 | 
| 
 | 
   589 	public DbType       DbType;
 | 
| 
 | 
   590 	public SqlDbType    SqlDbType;
 | 
| 
 | 
   591 	public long         Length;
 | 
| 
 | 
   592 	public int          Precision;
 | 
| 
 | 
   593 	public int          Scale;
 | 
| 
 | 
   594 	public string		Description;
 | 
| 
 | 
   595 
 | 
| 
 | 
   596 	public int          PKIndex = -1;
 | 
| 
 | 
   597 	public List<string> Attributes = new List<string>();
 | 
| 
 | 
   598 
 | 
| 
 | 
   599 	public bool IsPrimaryKey { get { return PKIndex >= 0; } }
 | 
| 
 | 
   600 }
 | 
| 
 | 
   601 
 | 
| 
 | 
   602 public enum AssociationType
 | 
| 
 | 
   603 {
 | 
| 
 | 
   604 	Auto,
 | 
| 
 | 
   605 	OneToOne,
 | 
| 
 | 
   606 	OneToMany,
 | 
| 
 | 
   607 	ManyToOne,
 | 
| 
 | 
   608 }
 | 
| 
 | 
   609 
 | 
| 
 | 
   610 public partial class ForeignKey
 | 
| 
 | 
   611 {
 | 
| 
 | 
   612 	public string       KeyName;
 | 
| 
 | 
   613 	public string       MemberName;
 | 
| 
 | 
   614 	public Table        OtherTable;
 | 
| 
 | 
   615 	public List<Column> ThisColumns  = new List<Column>();
 | 
| 
 | 
   616 	public List<Column> OtherColumns = new List<Column>();
 | 
| 
 | 
   617 	public List<string> Attributes   = new List<string>();
 | 
| 
 | 
   618 	public bool         CanBeNull    = true;
 | 
| 
 | 
   619 	public ForeignKey   BackReference;
 | 
| 
 | 
   620 
 | 
| 
 | 
   621 	private AssociationType _associationType = AssociationType.Auto;
 | 
| 
 | 
   622 	public  AssociationType  AssociationType
 | 
| 
 | 
   623 	{
 | 
| 
 | 
   624 		get { return _associationType; }
 | 
| 
 | 
   625 		set
 | 
| 
 | 
   626 		{
 | 
| 
 | 
   627 			_associationType = value;
 | 
| 
 | 
   628 
 | 
| 
 | 
   629 			if (BackReference != null)
 | 
| 
 | 
   630 			{
 | 
| 
 | 
   631 				switch (value)
 | 
| 
 | 
   632 				{
 | 
| 
 | 
   633 					case AssociationType.Auto      : BackReference.AssociationType = AssociationType.Auto;      break;
 | 
| 
 | 
   634 					case AssociationType.OneToOne  : BackReference.AssociationType = AssociationType.OneToOne;  break;
 | 
| 
 | 
   635 					case AssociationType.OneToMany : BackReference.AssociationType = AssociationType.ManyToOne; break;
 | 
| 
 | 
   636 					case AssociationType.ManyToOne : BackReference.AssociationType = AssociationType.OneToMany; break;
 | 
| 
 | 
   637 				}
 | 
| 
 | 
   638 			}
 | 
| 
 | 
   639 		}
 | 
| 
 | 
   640 	}
 | 
| 
 | 
   641 }
 | 
| 
 | 
   642 
 | 
| 
 | 
   643 #>
 |