diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2df1da5b5077d597142e85e19812ba900a4e81c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,270 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Database connection for t4 class generation from database
+**/*.generated.cs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+Resharper
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+#cake
+tools/*
+!tools/packages.config
+dist/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b339a45c43a1dcb4b80ab99e6224bc7232abd723
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,55 @@
+stages:
+  - test
+  - release
+  - releasetrigger
+
+cake:Test:
+  stage: test
+  script:
+    - PowerShell .\build.ps1 -Target Test -Configuration Debug
+  variables:
+    GIT_STRATEGY: clone
+  artifacts:
+    reports:
+      junit: "./Artifacts/TestResults.xml"
+    paths:
+      - "./Artifacts/*"
+  except:
+    - master
+    - tags
+
+cake:Release:
+  stage: release
+  script:
+    - PowerShell .\build.ps1 -Target Release -Configuration Release --nugetApiKey="${NUGET_API_KEY}"
+  variables:
+    GIT_STRATEGY: clone
+  dependencies:
+    - cake:Test
+  artifacts:
+    paths:
+      - "./Artifacts/*"
+  only:
+    - tags
+
+cake:Prerelease:
+  stage: release
+  script:
+    - PowerShell .\build.ps1 -Target Prerelease -Configuration Release
+  variables:
+    GIT_STRATEGY: clone
+  dependencies:
+    - cake:Test
+  artifacts:
+    paths:
+      - "./Artifacts/*"
+  except:
+    - tags
+    - master
+
+cake:GitlabRelease:
+    stage: releasetrigger
+    script:
+      - PowerShell .\build.ps1 -Target GitlabRelease --GitlabProjectPath="${CI_PROJECT_PATH}" --gitlabProjectId="${CI_PROJECT_ID}" --gitlabToken="${GITLAB_TOKEN}"
+    only:
+      - master
\ No newline at end of file
diff --git a/GitVersion.yml b/GitVersion.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1bdc0fe219f5f35d8a024a66d9fd715f44539640
--- /dev/null
+++ b/GitVersion.yml
@@ -0,0 +1,7 @@
+mode: ContinuousDeployment
+next-version: 1.0.0
+major-version-bump-message: 'Breaking:'
+minor-version-bump-message: '(Update|New):'
+patch-version-bump-message: 'Fix:'
+no-bump-message: '.*'
+commit-message-incrementing: Enabled
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..028e1445d83a05b6d68027507edb53033ca40ac3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 RWTH Aachen University
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/build.cake b/build.cake
new file mode 100644
index 0000000000000000000000000000000000000000..81648ff61bbee492e1bc7b4390eb8e0cc33d3056
--- /dev/null
+++ b/build.cake
@@ -0,0 +1,351 @@
+#tool nuget:?package=NUnit.ConsoleRunner&version=3.10.0
+#tool nuget:?package=vswhere&version=2.8.4
+#tool nuget:?package=GitVersion.CommandLine&version=5.1.3
+
+#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Json&version=4.0.0
+#addin nuget:https://api.nuget.org/v3/index.json?package=Newtonsoft.Json&version=11.0.2
+#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.FileHelpers&version=3.2.1
+
+using System.Net;
+using System.Net.Http;
+
+// Commandline arguments
+var target = Argument("target", "Default");
+var configuration = Argument("configuration", "Release");
+var nugetApiKey = Argument<string>("nugetApiKey", null);
+var version = Argument("nugetVersion", "");
+var gitlabProjectPath = Argument("gitlabProjectPath", "");
+var gitlabProjectId = Argument("gitlabProjectId", "");
+var gitlabToken = Argument("gitlabToken", "");
+
+// Define directories
+var projects = GetFiles("./**/*.csproj");
+var artifactsDir = Directory("./Artifacts");
+string nupkgDir;
+var solutionFile = GetFiles("./**/*.sln").First();
+var projectName = solutionFile.GetFilenameWithoutExtension().ToString();
+var nugetSource = "https://api.nuget.org/v3/index.json";
+var assemblyInfoSubPath = "Properties/AssemblyInfo.cs";
+var semanticVersion = "";
+string localNugetFeed;
+
+// get latest MSBuild version
+var vsLatest  = VSWhereLatest();	
+var msBuildPathX64 = (vsLatest == null) ? null : vsLatest.CombineWithFilePath("./MSBuild/Current/Bin/MSBuild.exe");
+
+Setup(context =>{
+	nupkgDir = $"{artifactsDir.ToString()}/nupkg";
+	var branch = GitVersion(new GitVersionSettings {
+			UpdateAssemblyInfo = false
+		}).BranchName.Replace("/", "-");
+
+	localNugetFeed = $"C:\\coscine\\LocalNugetFeeds\\{branch}";
+	Information("{0}", branch);
+	Information("Started at {0}", DateTime.Now);
+});
+
+Teardown(context =>{
+	Information("Finished at {0}", DateTime.Now);
+});
+
+Task("Clean")
+.Description("Cleans all build and artifacts directories")
+.Does(() =>{
+	var settings = new DeleteDirectorySettings {
+		Recursive = true,
+		Force = true
+	};
+	
+	var directoriesToClean = new List<DirectoryPath>();
+	
+	foreach(var project in projects) {
+		directoriesToClean.Add(Directory($"{project.GetDirectory()}/obj"));
+		directoriesToClean.Add(Directory($"{project.GetDirectory()}/bin"));
+	}
+	
+	directoriesToClean.Add(artifactsDir);
+
+	foreach(var dir in directoriesToClean) {
+		Information("Cleaning {0}", dir.ToString());
+		if (DirectoryExists(dir)) {
+			DeleteDirectory(dir, settings);
+			CreateDirectory(dir);
+		} else {
+			CreateDirectory(dir);
+		}
+	}
+});
+
+Task("Restore")
+.Does(() =>{
+	NuGetRestore(solutionFile, new NuGetRestoreSettings {
+		NoCache = true,
+		FallbackSource = new List<string>{ localNugetFeed },
+	});
+});
+
+Task("Test")
+.IsDependentOn("Build")
+.Does(() =>{
+	NUnit3($"./src/**/bin/{configuration}/*.Tests.dll", new NUnit3Settings {
+		// generate the xml file
+		NoResults = false,
+		Results = new NUnit3Result[] {
+			new NUnit3Result() {
+				FileName = $"{artifactsDir}/TestResults.xml",
+				Transform = $"{Context.Environment.WorkingDirectory}/nunit3-junit.xslt"
+			}
+		}
+	});
+});
+
+Task("GitVersion")
+.Does(() => {
+	if(string.IsNullOrWhiteSpace(version)) {
+		version = GitVersion(new GitVersionSettings {
+			UpdateAssemblyInfo = false
+		}).NuGetVersionV2;
+	}
+	var index = version.IndexOf("-");
+	semanticVersion = index > 0 ? version.Substring(0, index) : version;
+	Information("Version: {0}, SemanticVersion: {1}", version, semanticVersion);
+});
+
+Task("UpdateAssemblyInfo")
+.Does(() =>{
+	var index = version.IndexOf("-");
+	var semanticVersion = index > 0 ? version.Substring(0, index) : version;
+
+	foreach(var project in projects) {
+		CreateAssemblyInfo($"{project.GetDirectory()}/{assemblyInfoSubPath}", new AssemblyInfoSettings {
+			Product = project.GetFilenameWithoutExtension().ToString(),
+			Title = project.GetFilenameWithoutExtension().ToString(),
+			Company = "IT Center, RWTH Aachen University",
+			Version = semanticVersion,
+			FileVersion = semanticVersion,
+			InformationalVersion = version,
+			Copyright = $"{DateTime.Now.Year} IT Center, RWTH Aachen University",
+			Description = $"{project.GetFilenameWithoutExtension().ToString()} is a part of the CoScInE group."
+		});
+	}
+});
+
+Task("GitlabRelease")
+.IsDependentOn("GitVersion")
+.Does(() => {
+	var client = new HttpClient();
+	client.DefaultRequestHeaders.Add("PRIVATE-TOKEN", gitlabToken);
+	
+	// get the latest tag
+	var result = client.GetAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags").Result;
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Tag query failed.");
+	}
+
+	var tagList = result.Content.ReadAsStringAsync().Result;
+	var jArray = JArray.Parse(tagList);
+	// null if not tags exists yet
+	var lastTag = jArray.Select(x => x["name"]).FirstOrDefault();
+
+	var url = $"https://git.rwth-aachen.de/{gitlabProjectPath}";
+	
+	if(url.EndsWith(".git")) {
+		url = url.Substring(0, url.Length - ".git".Length);
+	}
+
+	if(url.EndsWith("/")) {
+		url = url.Substring(0, url.Length - 1);
+	}
+
+	var description = "";
+	// First line of description
+	// Gitlab compare url, if something can be compared
+	if(lastTag == null) {
+		description = $"# {semanticVersion} ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n";
+	} else {
+		description = $"# [{semanticVersion}]({url}/compare/{lastTag}...v{semanticVersion}) ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n";
+	}
+
+	// From when will messages be parsed, null results in all messages
+	var logParam = "";
+	if(lastTag != null) {
+		logParam = $"{lastTag}..Head";
+	}
+
+	Information(lastTag);
+
+	IEnumerable<string> redirectedStandardOutput;
+	var exitCodeWithArgument =
+		StartProcess(
+			"git",
+			new ProcessSettings {
+				Arguments = $"log {logParam} --pretty=format:HASH%h:%B",
+				RedirectStandardOutput = true
+			},
+			out redirectedStandardOutput
+		);
+
+	var prefixList = new Dictionary<string, List<string>>{
+		{"Fix", new List<string>()},
+		{"Update", new List<string>()},
+		{"New", new List<string>()},
+		{"Breaking", new List<string>()},
+		{"Docs", new List<string>()},
+		{"Build", new List<string>()},
+		{"Upgrade", new List<string>()},
+		{"Chore", new List<string>()},
+	};
+
+	var currentHash = "";
+	// Output last line of process output.
+	foreach(var line in redirectedStandardOutput) {
+		var commitMessage = "";
+		if(line.StartsWith("HASH")) {
+			currentHash = line.Substring("HASH".Length);
+			currentHash = currentHash.Substring(0, currentHash.IndexOf(":"));
+			commitMessage = line.Substring(currentHash.Length + line.IndexOf(currentHash) + 1);
+		} else {
+			commitMessage = line;
+		}
+
+		foreach(var kv in prefixList) {
+			if(commitMessage.StartsWith($"{kv.Key}:")) {
+				kv.Value.Add($"* {commitMessage.Substring(kv.Key.Length + 1).Trim()} {currentHash}");
+				break;
+			}
+		};
+	}
+	
+	foreach(var kv in prefixList) {
+		if(kv.Value.Any()) {
+			description += $" ### {kv.Key}\n\n";
+			foreach(var line in kv.Value) {
+				description += $"{line}\n";
+			}
+			description += "\n";
+		}
+	}
+	// correctly escape the json newlines
+	description = description.Replace("\n", "\\n");
+	Information("Description: {0}", description);
+
+	// create tag
+	result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags?tag_name=v{semanticVersion}&ref=master", null).Result;
+	Information("Create tag: {0}", result.Content.ReadAsStringAsync().Result);
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Tag creation failed.");
+	}
+
+	// create release
+	var json = $"{{\"name\": \"v{semanticVersion}\", \"tag_name\": \"v{semanticVersion}\", \"description\": \"{description}\"}}";
+	var content = new StringContent(json, Encoding.UTF8, "application/json");
+	result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/releases", content).Result;
+	Information("Create release: {0}", result.Content.ReadAsStringAsync().Result);
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Release creation failed.");
+	}
+});
+
+Task("Build")
+.IsDependentOn("Clean")
+.IsDependentOn("GitVersion")
+.IsDependentOn("UpdateAssemblyInfo")
+.IsDependentOn("Restore")
+.Does(() =>{
+		var frameworkSettingsWindows = new MSBuildSettings {
+			Configuration = configuration
+		};
+		
+		frameworkSettingsWindows.ToolPath = msBuildPathX64;
+		frameworkSettingsWindows.WorkingDirectory = Context.Environment.WorkingDirectory;
+
+		if (configuration.Equals("Release")) {
+			frameworkSettingsWindows.WithProperty("DebugSymbols", "false");
+			frameworkSettingsWindows.WithProperty("DebugType", "None");
+		}
+
+		// Use MSBuild
+		Information("Building {0}", solutionFile);
+		MSBuild(solutionFile, frameworkSettingsWindows);
+});
+
+Task("NugetPack")
+.IsDependentOn("Build")
+.Does(() =>{
+	foreach(var project in projects) {
+			var nuspec = $"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec";
+			if(!project.ToString().EndsWith(".Tests") && FileExists(nuspec))
+			{
+				var settings = new NuGetPackSettings 
+				{
+					OutputDirectory = nupkgDir,
+					Version = version,
+					Properties = new Dictionary<string, string>
+					{
+						{ "Configuration", configuration}
+					}
+				};				
+				NuGetPack(project.ToString(), settings);
+			}
+		}
+});
+
+Task("NugetPush")
+.IsDependentOn("NugetPack")
+.Does(() =>{
+	var nupkgs = GetFiles($"{nupkgDir}/*.nupkg");
+	Information("Need to push {0} packages", nupkgs.Count);
+	if(!String.IsNullOrWhiteSpace(nugetApiKey)) {
+		foreach(var nupkg in nupkgs) {
+			Information("Pushing {0}", nupkg);
+			NuGetPush(nupkg, new NuGetPushSettings {
+				Source = nugetSource,
+				ApiKey = nugetApiKey
+			});
+		}
+	} else {
+		Information("NugetApiKey is not set. Can't push.");
+		throw new Exception("NugetApiKey is not set. Can't push.");
+	}
+});
+
+Task("CopyToArtifacts")
+.Does(() =>{
+	foreach(var project in projects) {
+		if(!project.GetDirectory().ToString().EndsWith(".Tests")
+		&& !FileExists($"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec")
+		&& DirectoryExists(project.GetDirectory()))
+		{
+			Information("Copying {0}/* to {1}", $"{project.GetDirectory()}/bin/{configuration}", artifactsDir);
+			CopyDirectory($"{project.GetDirectory()}/bin/{configuration}/", artifactsDir);
+		}
+	}
+});
+
+Task("NugetPushLocal")
+.IsDependentOn("NugetPack")
+.Does(() =>{	
+	var nupkgs = GetFiles($"{nupkgDir}/*.nupkg");
+	foreach(var nupkg in nupkgs) {
+		if(!DirectoryExists(localNugetFeed)) {
+			CreateDirectory(localNugetFeed);
+		}
+		CopyFile(nupkg.ToString(), $"{localNugetFeed}\\{nupkg.GetFilename()}");
+	}
+});
+
+Task("Prerelease")
+.IsDependentOn("Build")
+.IsDependentOn("CopyToArtifacts")
+.IsDependentOn("NugetPushLocal");
+
+Task("Release")
+.IsDependentOn("NugetPack")
+.IsDependentOn("CopyToArtifacts")
+.IsDependentOn("NugetPushLocal")
+.IsDependentOn("NugetPush");
+
+Task("Default")
+.IsDependentOn("Test");
+
+RunTarget(target);
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..f83382e8e4092ba6cf32a47f9dfa4e211c878430
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,255 @@
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 - 2016 Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy of
+#this software and associated documentation files (the "Software"), to deal in
+#the Software without restriction, including without limitation the rights to
+#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+#the Software, and to permit persons to whom the Software is furnished to do so,
+#subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+##########################################################################
+# This is the Cake bootstrapper script for PowerShell.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+<#
+
+.SYNOPSIS
+This is a Powershell script to bootstrap a Cake build.
+
+.DESCRIPTION
+This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
+and execute your Cake build script with the parameters you provide.
+
+.PARAMETER Script
+The build script to execute.
+.PARAMETER Target
+The build script target to run.
+.PARAMETER Configuration
+The build configuration to use.
+.PARAMETER Verbosity
+Specifies the amount of information to be displayed.
+.PARAMETER ShowDescription
+Shows description about tasks.
+.PARAMETER DryRun
+Performs a dry run.
+.PARAMETER Experimental
+Uses the nightly builds of the Roslyn script engine.
+.PARAMETER Mono
+Uses the Mono Compiler rather than the Roslyn script engine.
+.PARAMETER SkipToolPackageRestore
+Skips restoring of packages.
+.PARAMETER ScriptArgs
+Remaining arguments are added here.
+
+.LINK
+https://cakebuild.net
+
+#>
+
+[CmdletBinding()]
+Param(
+    [string]$Script = "build.cake",
+    [string]$Target,
+    [string]$Configuration,
+    [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
+    [string]$Verbosity,
+    [switch]$ShowDescription,
+    [Alias("WhatIf", "Noop")]
+    [switch]$DryRun,
+    [switch]$Experimental,
+    [switch]$Mono,
+    [switch]$SkipToolPackageRestore,
+    [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
+    [string[]]$ScriptArgs
+)
+
+[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
+function MD5HashFile([string] $filePath)
+{
+    if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
+    {
+        return $null
+    }
+
+    [System.IO.Stream] $file = $null;
+    [System.Security.Cryptography.MD5] $md5 = $null;
+    try
+    {
+        $md5 = [System.Security.Cryptography.MD5]::Create()
+        $file = [System.IO.File]::OpenRead($filePath)
+        return [System.BitConverter]::ToString($md5.ComputeHash($file))
+    }
+    finally
+    {
+        if ($file -ne $null)
+        {
+            $file.Dispose()
+        }
+    }
+}
+
+function GetProxyEnabledWebClient
+{
+    $wc = New-Object System.Net.WebClient
+    $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
+    $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials        
+    $wc.Proxy = $proxy
+    return $wc
+}
+
+Write-Host "Preparing to run build script..."
+
+if(!$PSScriptRoot){
+    $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+}
+
+$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
+$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins"
+$MODULES_DIR = Join-Path $TOOLS_DIR "Modules"
+$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
+$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
+$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
+$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
+$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config"
+$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
+
+# Make sure tools folder exists
+if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
+    Write-Verbose -Message "Creating tools directory..."
+    New-Item -Path $TOOLS_DIR -Type directory | out-null
+}
+
+# Make sure that packages.config exist.
+if (!(Test-Path $PACKAGES_CONFIG)) {
+    Write-Verbose -Message "Downloading packages.config..."    
+    try {        
+        $wc = GetProxyEnabledWebClient
+        $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
+        Throw "Could not download packages.config."
+    }
+}
+
+# Try find NuGet.exe in path if not exists
+if (!(Test-Path $NUGET_EXE)) {
+    Write-Verbose -Message "Trying to find nuget.exe in PATH..."
+    $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) }
+    $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
+    if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
+        Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
+        $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+    }
+}
+
+# Try download NuGet.exe if not exists
+if (!(Test-Path $NUGET_EXE)) {
+    Write-Verbose -Message "Downloading NuGet.exe..."
+    try {
+        $wc = GetProxyEnabledWebClient
+        $wc.DownloadFile($NUGET_URL, $NUGET_EXE)
+    } catch {
+        Throw "Could not download NuGet.exe."
+    }
+}
+
+# Save nuget.exe path to environment to be available to child processed
+$ENV:NUGET_EXE = $NUGET_EXE
+
+# Restore tools from NuGet?
+if(-Not $SkipToolPackageRestore.IsPresent) {
+    Push-Location
+    Set-Location $TOOLS_DIR
+
+    # Check for changes in packages.config and remove installed tools if true.
+    [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
+    if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
+      ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
+        Write-Verbose -Message "Missing or changed package.config hash..."
+        Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+    }
+
+    Write-Verbose -Message "Restoring tools from NuGet..."
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
+
+    if ($LASTEXITCODE -ne 0) {
+        Throw "An error occurred while restoring NuGet tools."
+    }
+    else
+    {
+        $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
+    }
+    Write-Verbose -Message ($NuGetOutput | out-string)
+
+    Pop-Location
+}
+
+# Restore addins from NuGet
+if (Test-Path $ADDINS_PACKAGES_CONFIG) {
+    Push-Location
+    Set-Location $ADDINS_DIR
+
+    Write-Verbose -Message "Restoring addins from NuGet..."
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
+
+    if ($LASTEXITCODE -ne 0) {
+        Throw "An error occurred while restoring NuGet addins."
+    }
+
+    Write-Verbose -Message ($NuGetOutput | out-string)
+
+    Pop-Location
+}
+
+# Restore modules from NuGet
+if (Test-Path $MODULES_PACKAGES_CONFIG) {
+    Push-Location
+    Set-Location $MODULES_DIR
+
+    Write-Verbose -Message "Restoring modules from NuGet..."
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
+
+    if ($LASTEXITCODE -ne 0) {
+        Throw "An error occurred while restoring NuGet modules."
+    }
+
+    Write-Verbose -Message ($NuGetOutput | out-string)
+
+    Pop-Location
+}
+
+# Make sure that Cake has been installed.
+if (!(Test-Path $CAKE_EXE)) {
+    Throw "Could not find Cake.exe at $CAKE_EXE"
+}
+
+
+
+# Build Cake arguments
+$cakeArguments = @("$Script");
+if ($Target) { $cakeArguments += "-target=$Target" }
+if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
+if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
+if ($ShowDescription) { $cakeArguments += "-showdescription" }
+if ($DryRun) { $cakeArguments += "-dryrun" }
+if ($Experimental) { $cakeArguments += "-experimental" }
+if ($Mono) { $cakeArguments += "-mono" }
+$cakeArguments += $ScriptArgs
+
+# Start Cake
+Write-Host "Running build script..."
+&$CAKE_EXE $cakeArguments
+exit $LASTEXITCODE
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d088917ed78538ff57cf654cf71aad6bf045d655
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,122 @@
+#!/usr/bin/env bash
+
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 - 2016 Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy of
+#this software and associated documentation files (the "Software"), to deal in
+#the Software without restriction, including without limitation the rights to
+#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+#the Software, and to permit persons to whom the Software is furnished to do so,
+#subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+##########################################################################
+# This is the Cake bootstrapper script for Linux and OS X.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+# Define directories.
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+TOOLS_DIR=$SCRIPT_DIR/tools
+NUGET_EXE=$TOOLS_DIR/nuget.exe
+CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
+PACKAGES_CONFIG=$TOOLS_DIR/packages.config
+PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
+
+# Define md5sum or md5 depending on Linux/OSX
+MD5_EXE=
+if [[ "$(uname -s)" == "Darwin" ]]; then
+    MD5_EXE="md5 -r"
+else
+    MD5_EXE="md5sum"
+fi
+
+# Define default arguments.
+SCRIPT="build.cake"
+TARGET="Default"
+CONFIGURATION="Release"
+VERBOSITY="verbose"
+DRYRUN=
+SHOW_VERSION=false
+SCRIPT_ARGUMENTS=()
+
+# Parse arguments.
+for i in "$@"; do
+    case $1 in
+        -s|--script) SCRIPT="$2"; shift ;;
+        -t|--target) TARGET="$2"; shift ;;
+        -c|--configuration) CONFIGURATION="$2"; shift ;;
+        -v|--verbosity) VERBOSITY="$2"; shift ;;
+        -d|--dryrun) DRYRUN="-dryrun" ;;
+        --version) SHOW_VERSION=true ;;
+        --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
+        *) SCRIPT_ARGUMENTS+=("$1") ;;
+    esac
+    shift
+done
+
+# Make sure the tools folder exist.
+if [ ! -d "$TOOLS_DIR" ]; then
+  mkdir "$TOOLS_DIR"
+fi
+
+# Make sure that packages.config exist.
+if [ ! -f "$TOOLS_DIR/packages.config" ]; then
+    echo "Downloading packages.config..."
+    curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages
+    if [ $? -ne 0 ]; then
+        echo "An error occurred while downloading packages.config."
+        exit 1
+    fi
+fi
+
+# Download NuGet if it does not exist.
+if [ ! -f "$NUGET_EXE" ]; then
+    echo "Downloading NuGet..."
+    curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
+    if [ $? -ne 0 ]; then
+        echo "An error occurred while downloading nuget.exe."
+        exit 1
+    fi
+fi
+
+# Restore tools from NuGet.
+pushd "$TOOLS_DIR" >/dev/null
+if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then
+    find . -type d ! -name . | xargs rm -rf
+fi
+
+mono "$NUGET_EXE" install -ExcludeVersion
+if [ $? -ne 0 ]; then
+    echo "Could not restore NuGet packages."
+    exit 1
+fi
+
+$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5
+
+popd >/dev/null
+
+# Make sure that Cake has been installed.
+if [ ! -f "$CAKE_EXE" ]; then
+    echo "Could not find Cake.exe at '$CAKE_EXE'."
+    exit 1
+fi
+
+# Start Cake
+if $SHOW_VERSION; then
+    exec mono "$CAKE_EXE" -version
+else
+    exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
+fi
\ No newline at end of file
diff --git a/nunit3-junit.xslt b/nunit3-junit.xslt
new file mode 100644
index 0000000000000000000000000000000000000000..bf69bdb1d2cd6fc2fdbeb915b4eb6732f720848e
--- /dev/null
+++ b/nunit3-junit.xslt
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Taken from: https://github.com/nunit/nunit-transforms/tree/master/nunit3-junit
+-->
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:template match="/test-run">
+    <testsuites tests="{@testcasecount}" failures="{@failed}" disabled="{@skipped}" time="{@duration}">
+      <xsl:apply-templates/>
+    </testsuites>
+  </xsl:template>
+
+  <xsl:template match="test-suite">
+    <xsl:if test="test-case">
+      <testsuite tests="{@testcasecount}" time="{@duration}" errors="{@testcasecount - @passed - @skipped - @failed}" failures="{@failed}" skipped="{@skipped}" timestamp="{@start-time}">
+        <xsl:attribute name="name">
+          <xsl:for-each select="ancestor-or-self::test-suite/@name">
+            <xsl:value-of select="concat(., '.')"/>
+          </xsl:for-each>
+        </xsl:attribute>
+        <xsl:apply-templates select="test-case"/>
+      </testsuite>
+      <xsl:apply-templates select="test-suite"/>
+    </xsl:if>
+    <xsl:if test="not(test-case)">
+      <xsl:apply-templates/>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="test-case">
+    <testcase name="{@name}" assertions="{@asserts}" time="{@duration}" status="{@result}" classname="{@classname}">
+      <xsl:if test="@runstate = 'Skipped' or @runstate = 'Ignored'">
+        <skipped/>
+      </xsl:if>
+      
+      <xsl:apply-templates/>
+    </testcase>
+  </xsl:template>
+
+  <xsl:template match="command-line"/>
+  <xsl:template match="settings"/>
+
+  <xsl:template match="output">
+    <system-out>
+      <xsl:value-of select="."/>
+    </system-out>
+  </xsl:template>
+
+  <xsl:template match="stack-trace">
+  </xsl:template>
+
+  <xsl:template match="test-case/failure">
+    <failure message="{./message}">
+      <xsl:value-of select="./stack-trace"/>
+    </failure>
+  </xsl:template>
+
+  <xsl:template match="test-suite/failure"/>
+
+  <xsl:template match="test-case/reason">
+    <skipped message="{./message}"/>
+  </xsl:template>
+  
+  <xsl:template match="test-case/assertions">
+  </xsl:template>
+
+  <xsl:template match="test-suite/reason"/>
+
+  <xsl:template match="properties"/>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/src/.tools/linq2db.t4models/FirebirdSql.Data.FirebirdClient.dll b/src/.tools/linq2db.t4models/FirebirdSql.Data.FirebirdClient.dll
new file mode 100644
index 0000000000000000000000000000000000000000..dd8e0105289d37e4be97c1419fd12a2cbc6e00c4
Binary files /dev/null and b/src/.tools/linq2db.t4models/FirebirdSql.Data.FirebirdClient.dll differ
diff --git a/src/.tools/linq2db.t4models/Init.ps1 b/src/.tools/linq2db.t4models/Init.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..d7e710d55907097cf93d3d3e546801028e12d906
--- /dev/null
+++ b/src/.tools/linq2db.t4models/Init.ps1
@@ -0,0 +1,9 @@
+param($installPath, $toolsPath, $package, $project)
+
+# get the active solution
+$solution           = Get-Interface $dte.Solution ([EnvDTE80.Solution2])
+$solutionPath       = [System.IO.Path]::GetDirectoryName($solution.FullName)
+$linq2dbToolsPath   = [System.IO.Path]::Combine($solutionPath, ".tools", "linq2db.t4models")
+
+# tools copy
+xcopy $("$toolsPath\*.*") $("$linq2dbToolsPath\") /y /e
diff --git a/src/.tools/linq2db.t4models/Microsoft.SqlServer.Types.dll b/src/.tools/linq2db.t4models/Microsoft.SqlServer.Types.dll
new file mode 100644
index 0000000000000000000000000000000000000000..d4dd789939d82c83eb2720bf5868234ffafca86d
Binary files /dev/null and b/src/.tools/linq2db.t4models/Microsoft.SqlServer.Types.dll differ
diff --git a/src/.tools/linq2db.t4models/MySql.Data.dll b/src/.tools/linq2db.t4models/MySql.Data.dll
new file mode 100644
index 0000000000000000000000000000000000000000..d97ad46b903f211ecb4e3e09bc44e7128ec887e2
Binary files /dev/null and b/src/.tools/linq2db.t4models/MySql.Data.dll differ
diff --git a/src/.tools/linq2db.t4models/Npgsql.dll b/src/.tools/linq2db.t4models/Npgsql.dll
new file mode 100644
index 0000000000000000000000000000000000000000..c814b2681c107eac00cbb32812954bc9d163ba73
Binary files /dev/null and b/src/.tools/linq2db.t4models/Npgsql.dll differ
diff --git a/src/.tools/linq2db.t4models/Oracle.ManagedDataAccess.dll b/src/.tools/linq2db.t4models/Oracle.ManagedDataAccess.dll
new file mode 100644
index 0000000000000000000000000000000000000000..c228b7093fb73194e9bf9689d99b1154a963cf15
Binary files /dev/null and b/src/.tools/linq2db.t4models/Oracle.ManagedDataAccess.dll differ
diff --git a/src/.tools/linq2db.t4models/SQLite.Interop.dll b/src/.tools/linq2db.t4models/SQLite.Interop.dll
new file mode 100644
index 0000000000000000000000000000000000000000..5b872055f5a4b1b759bfa0811901675d4c01346b
Binary files /dev/null and b/src/.tools/linq2db.t4models/SQLite.Interop.dll differ
diff --git a/src/.tools/linq2db.t4models/System.Data.SQLite.dll b/src/.tools/linq2db.t4models/System.Data.SQLite.dll
new file mode 100644
index 0000000000000000000000000000000000000000..59f3dcc375988dbd291f100bd06f259b88a887e0
Binary files /dev/null and b/src/.tools/linq2db.t4models/System.Data.SQLite.dll differ
diff --git a/src/.tools/linq2db.t4models/System.Threading.Tasks.Extensions.dll b/src/.tools/linq2db.t4models/System.Threading.Tasks.Extensions.dll
new file mode 100644
index 0000000000000000000000000000000000000000..6807cbd9ba040b9f721a03d7fbe6bc0ec088d50b
Binary files /dev/null and b/src/.tools/linq2db.t4models/System.Threading.Tasks.Extensions.dll differ
diff --git a/src/.tools/linq2db.t4models/linq2db.dll b/src/.tools/linq2db.t4models/linq2db.dll
new file mode 100644
index 0000000000000000000000000000000000000000..bcbdac1d0742aad9fe3866797e3036961812b53d
Binary files /dev/null and b/src/.tools/linq2db.t4models/linq2db.dll differ
diff --git a/src/Version.sln b/src/Version.sln
new file mode 100644
index 0000000000000000000000000000000000000000..df813aa1ad58934516a0840df2b8f7b8e618f62f
--- /dev/null
+++ b/src/Version.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30523.141
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Version", "Version\Version.csproj", "{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {08320DB2-75D1-493F-997C-03CD85808E87}
+	EndGlobalSection
+EndGlobal
diff --git a/src/Version/App.config b/src/Version/App.config
new file mode 100644
index 0000000000000000000000000000000000000000..9a78cf9f40f376983adf6b40c385c1e5f2bfecd6
--- /dev/null
+++ b/src/Version/App.config
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+    </configSections>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+    </startup>
+    <entityFramework>
+        <providers>
+            <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+        </providers>
+    </entityFramework>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="linq2db" publicKeyToken="e41013125f9e410a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.1.0" newVersion="3.1.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Configuration.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Logging" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Primitives" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.FileProviders.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.1.1.1" newVersion="4.1.1.1" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.3.1" newVersion="4.0.3.1" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Http" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.2.0" newVersion="2.2.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Http.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Hosting.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Hosting.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Http.Features" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Routing.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Routing" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.2.0" newVersion="2.2.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Mvc.Core" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.2.0" newVersion="2.2.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-1.4.3.0" newVersion="1.4.3.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Authorization" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Mvc.ApiExplorer" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Options" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Mvc.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Mvc.Formatters.Json" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.StaticFiles" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Security.Cryptography.Cng" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>
\ No newline at end of file
diff --git a/src/Version/Controllers/VersionController.cs b/src/Version/Controllers/VersionController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e301c1e7b2e20dd007e1ae64961bcae4d955e49a
--- /dev/null
+++ b/src/Version/Controllers/VersionController.cs
@@ -0,0 +1,65 @@
+using Coscine.Configuration;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Coscine.Api.Version.Controllers
+{
+    public class VersionController : Controller
+    {
+
+        private readonly IConfiguration _configuration;
+
+
+        public VersionController(ILogger<VersionController> logger)
+        {
+            _configuration = Program.Configuration;
+
+        }
+        [HttpGet("[controller]/versions")]
+        public IActionResult Versions()
+        {
+            JObject Versions = new JObject();
+            Versions.Add("api", GetEntries("apis"));
+            Versions.Add("app", GetEntries("apps"));
+            Versions.Add("dlls", GetEntries("dlls"));
+            Versions.Add("scripts", GetEntries("scripts"));
+            Versions.Add("sharepoint", GetEntries("sharepoint"));
+            Versions.Add("cron", GetEntries("cron"));
+            return Json(Versions);
+        }
+
+        public JArray GetEntries(string name)
+        {
+            var Infos = new JArray();
+            try { 
+            var stringlist = _configuration.Keys("coscine/" + name + "/");
+            var array = stringlist.Select((entry) => entry.Substring(0, entry.LastIndexOf("/") + 1))
+                                        .Distinct().ToArray();
+     
+                foreach (var entry in array)
+                {
+                    var Version = _configuration.GetString(entry + "version");
+                    var Name = _configuration.GetString(entry + "name");
+                    var Port = _configuration.GetString(entry + "port");
+
+                    var Info = new JObject
+                    {
+                        ["name"] = Name,
+                        ["version"] = Version,
+                        ["port"] = Port
+                    };
+                    Infos.Add(Info);
+                }
+             
+            }
+            catch
+            {
+            }
+            return Infos;
+        }
+    }
+}
diff --git a/src/Version/LinqToDB.Templates/CopyMe.Access.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.Access.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..01f9aed963515d8a1ae1cf6e091b0253dae602ae
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.Access.tt.txt
@@ -0,0 +1,46 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                        #>
+<#@ output extension=".generated.cs"                                               #>
+<#@ include file="$(LinqToDBT4AccessTemplatesDirectory)LinqToDB.Access.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4AccessTemplatesDirectory)PluralizationService.ttinclude"  #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.Access.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"  #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" providerName="Access"
+					connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=MyDatabase.mdb;Locale Identifier=1033;Jet OLEDB:Engine Type=5;Persist Security Info=True" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadAccessMetadata(@"C:\Data", "MyDatabase.mdb");
+//	LoadAccessMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.DB2.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.DB2.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..611011da4fed824c029df80fdab44e53a60b8f49
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.DB2.tt.txt
@@ -0,0 +1,50 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                       #>
+<#@ output extension=".generated.cs"                                              #>
+<#@ include file="$(LinqToDBT4DB2TemplatesDirectory)LinqToDB.DB2.Tools.ttinclude"   #>
+<#@ include file="$(LinqToDBT4DB2TemplatesDirectory)PluralizationService.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.DB2.Tools.ttinclude"   #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude" #>
+<#
+	/*
+		1. Download and install IBM Data Server Provider for .NET.
+
+		2. Add a reference to IBM.Data.DB2.dll.
+
+		3. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		4. Modify the connection settings below to connect to your database.
+
+		5. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" providerName="DB2"
+					connectionString="Server=MyServer:50000;Database=MyDatabase;UID=MyUser;PWD=TestPassword;" />
+			</connectionStrings>
+
+		6. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		7. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadDB2Metadata("MyServer", "50000", "MyDatabase", "MyUser", "TestPassword");
+//	LoadDB2Metadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.Firebird.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.Firebird.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f3d2559e053ba0ba0340d4e1dcf86f99f610598a
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.Firebird.tt.txt
@@ -0,0 +1,46 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                          #>
+<#@ output extension=".generated.cs"                                                 #>
+<#@ include file="$(LinqToDBT4FirebirdTemplatesDirectory)LinqToDB.Firebird.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4FirebirdTemplatesDirectory)PluralizationService.ttinclude"    #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.Firebird.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"    #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="DataSource=MyServer;Database=C:\Data\MyDatabase.fdb;User Id=SYSDBA;Password=masterkey" providerName="Firebird" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadFirebirdMetadata("MyServer", @"C:\Data\MyDatabase.fdb");
+//	LoadFirebirdMetadata(string server, string database, string uid, string password);
+//	LoadFirebirdMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.Informix.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.Informix.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..17acc1fc73fd405e8fc72106fb3859d9f4dc9ce6
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.Informix.tt.txt
@@ -0,0 +1,51 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                          #>
+<#@ output extension=".generated.cs"                                                 #>
+<#@ include file="$(LinqToDBT4InformixTemplatesDirectory)LinqToDB.Informix.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4InformixTemplatesDirectory)PluralizationService.ttinclude"    #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.Informix.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"    #>
+<#
+	/*
+		1. Download and install IBM Data Server Provider for .NET.
+
+		2. Add a reference to IBM.Data.Informix.dll.
+
+		3. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		4. Modify the connection settings below to connect to your database.
+
+		5. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase"
+					connectionString="Host=MyServer;Service=9088;Server=ol_informix1170;Protocol=onsoctcp;Database=MyDatabase;UID=informix;PWD=TestPassword;"
+					providerName="IBM.Data.Informix"/>
+			</connectionStrings>
+
+		6. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		7. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadInformixMetadata("MyServer", "9088", "ol_informix1170", "MyDatabase", "informix", "TestPassword");
+//	LoadInformixMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.MySql.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.MySql.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..173d74fa74253225d96a9fe552999988d1247b1d
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.MySql.tt.txt
@@ -0,0 +1,45 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                       #>
+<#@ output extension=".generated.cs"                                              #>
+<#@ include file="$(LinqToDBT4MySqlTemplatesDirectory)LinqToDB.MySql.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4MySqlTemplatesDirectory)PluralizationService.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.MySql.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude" #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Server=MyServer;Port=3306;Database=MyDatabase;Uid=root;Pwd=TestPassword;charset=utf8;" providerName="MySql.Data.MySqlClient" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadMySqlMetadata("MyServer", "MyDatabase", "root", "TestPassword");
+//	LoadMySqlMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.Oracle.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.Oracle.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..16b17cab5f4bd5b3468af299008663b363e19ea8
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.Oracle.tt.txt
@@ -0,0 +1,45 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                        #>
+<#@ output extension=".generated.cs"                                               #>
+<#@ include file="$(LinqToDBT4OracleTemplatesDirectory)LinqToDB.Oracle.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4OracleTemplatesDirectory)PluralizationService.ttinclude"  #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.Oracle.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"  #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyServer)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=MyDatabase)));User Id=MyUser;Password=MyPassword;" providerName="Oracle" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadOracleMetadata("MyServer", "1521", "MyDatabase", "MyUser", "MyPassword");
+//	LoadOracleMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.PostgreSQL.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.PostgreSQL.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..801611a896edbc93cd6541eaa45ae2e60cfbf936
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.PostgreSQL.tt.txt
@@ -0,0 +1,45 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                            #>
+<#@ output extension=".generated.cs"                                                   #>
+<#@ include file="$(LinqToDBT4PostgreSQLTemplatesDirectory)LinqToDB.PostgreSQL.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4PostgreSQLTemplatesDirectory)PluralizationService.ttinclude"      #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.PostgreSQL.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"      #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Server=MyServer;Port=5432;Database=MyDatabase;User Id=postgres;Password=TestPassword;Pooling=true;MinPoolSize=10;MaxPoolSize=100;Protocol=3;" providerName="PostgreSQL" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadPostgreSQLMetadata("MyServer", "5432", "MyDatabase", "postgres", "TestPassword");
+//	LoadPostgreSQLMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.SQLite.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.SQLite.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d0d8f08812059acae99cf83bc735018f97f2de3a
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.SQLite.tt.txt
@@ -0,0 +1,45 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                        #>
+<#@ output extension=".generated.cs"                                               #>
+<#@ include file="$(LinqToDBT4SQLiteTemplatesDirectory)LinqToDB.SQLite.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4SQLiteTemplatesDirectory)PluralizationService.ttinclude"  #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.SQLite.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"  #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Data Source=MyDatabase.sqlite" providerName="SQLite" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadSQLiteMetadata(@"C:\Data", "MyDatabase.sqlite");
+//	LoadSQLiteMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.SapHana.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.SapHana.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7c79bf9e504ab5f80552069e9f34c8cf343f7a78
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.SapHana.tt.txt
@@ -0,0 +1,49 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                         #>
+<#@ output extension=".generated.cs"                                                #>
+<#@ include file="$(LinqToDBT4SapHanaTemplatesDirectory)LinqToDB.SapHana.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4SapHanaTemplatesDirectory)PluralizationService.ttinclude"   #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.SapHana.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"   #>
+<#
+	/*
+		1. Download and install SapHana data provider for .NET.
+
+		2. Add a reference to Sap.Data.Hana.dll.
+
+		3. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		4. Modify the connection settings below to connect to your database.
+
+		5. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Server=hanahost:port;Current Schema=TEST;UserID=Test;Password=TestPassword;" providerName="Sap.Data.Hana" />
+			</connectionStrings>
+
+		6. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		7. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadSapHanaMetadata("MyServer", "MyDatabase", "TestUser", "TestPassword");
+//	LoadSapHanaMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.SqlCe.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.SqlCe.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..386b3a0b29c496403ff67f1dc7b99ca14b2293bc
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.SqlCe.tt.txt
@@ -0,0 +1,45 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                       #>
+<#@ output extension=".generated.cs"                                              #>
+<#@ include file="$(LinqToDBT4SqlCeTemplatesDirectory)LinqToDB.SqlCe.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4SqlCeTemplatesDirectory)PluralizationService.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.SqlCe.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude" #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Data Source=MyDatabase.sdf" providerName="System.Data.SqlServerCe" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadSqlCeMetadata(@"C:\Data", "MyDatabase.sdf");
+//	LoadSqlCeMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.SqlServer.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.SqlServer.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..891b6b7b8f425a77475c43995b6d0d807b198483
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.SqlServer.tt.txt
@@ -0,0 +1,56 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                           #>
+<#@ output extension=".generated.cs"                                                  #>
+<#@ include file="$(LinqToDBT4SqlServerTemplatesDirectory)LinqToDB.SqlServer.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4SqlServerTemplatesDirectory)PluralizationService.ttinclude"     #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.SqlServer.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"     #>
+<#
+	/*
+		1. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		2. Modify the connection settings below to connect to your database.
+
+		3. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" providerName="System.Data.SqlClient"
+					connectionString="Data Source=.;Database=MyDatabase;User Id=User;Password=TestPassword;" />
+			</connectionStrings>
+
+		4. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		5. See more at https://github.com/linq2db/t4models
+
+		If you need to use the Microsoft.SqlServer.Types namespace, install the Microsoft.SqlServer.Types nuget,
+		and replace the following include at the top of this file:
+
+			"$(ProjectDir)LinqToDB.Templates\LinqToDB.SqlServer.Tools.ttinclude"
+
+		with
+
+			"$(ProjectDir)LinqToDB.Templates\LinqToDB.SqlServer.SqlTypes.Tools.ttinclude"
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadSqlServerMetadata("MyServer", "MyDatabase", "User", "Password");
+//	LoadSqlServerMetadata(".", "MyDatabase"); // Integrated Security
+//	LoadSqlServerMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/CopyMe.Sybase.tt.txt b/src/Version/LinqToDB.Templates/CopyMe.Sybase.tt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..edbad0dc74d407c83fee3c18a0d08fc5ead3f29f
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/CopyMe.Sybase.tt.txt
@@ -0,0 +1,49 @@
+<#@ template language="C#" debug="True" hostSpecific="True"                        #>
+<#@ output extension=".generated.cs"                                               #>
+<#@ include file="$(LinqToDBT4SybaseTemplatesDirectory)LinqToDB.Sybase.Tools.ttinclude" #>
+<#@ include file="$(LinqToDBT4SybaseTemplatesDirectory)PluralizationService.ttinclude"  #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\LinqToDB.Sybase.Tools.ttinclude" #>
+<# //@ include file="$(ProjectDir)LinqToDB.Templates\PluralizationService.ttinclude"  #>
+<#
+	/*
+		1. Download and install Sybase data provider for .NET.
+
+		2. Add a reference to Sybase.AdoNet2(4).AseClient.dll.
+
+		3. Create new *.tt file (e.g. MyDatabase.tt) in a folder where you would like to generate your data model
+		   and copy content from this file to it. For example:
+
+			MyProject
+				DataModels
+					MyDatabase.tt
+
+		4. Modify the connection settings below to connect to your database.
+
+		5. Add connection string to the web/app.config file:
+
+			<connectionStrings>
+				<add name="MyDatabase" connectionString="Data Source=MyServer;Port=5000;Database=MyDatabase;Uid=sa;Password=TestPassword;Charset=utf8;" providerName="Sybase" />
+			</connectionStrings>
+
+		6. To access your database use the following code:
+
+			using (var db = new MyDatabaseDB())
+			{
+				var q =
+					from c in db.Customers
+					select c;
+
+				foreach (var c in q)
+					Console.WriteLine(c.ContactName);
+			}
+
+		7. See more at https://github.com/linq2db/t4models
+	*/
+
+	NamespaceName = "DataModels";
+
+	LoadSybaseMetadata("MyServer", "5000", "MyDatabase", "sa", "TestPassword");
+//	LoadSybaseMetadata(string connectionString);
+
+	GenerateModel();
+#>
diff --git a/src/Version/LinqToDB.Templates/DataAnnotations.ttinclude b/src/Version/LinqToDB.Templates/DataAnnotations.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..a98aea24cf313345913d948297bba0784055801a
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/DataAnnotations.ttinclude
@@ -0,0 +1,65 @@
+<#
+	{
+		var beforeGenerateModel = BeforeGenerateModel;
+		BeforeGenerateModel = () =>
+		{
+			beforeGenerateModel();
+			DataAnnotationsImpl();
+		};
+	}
+#>
+<#+
+void DataAnnotationsImpl()
+{
+	foreach (Class cl in GetTreeNodes(Model).OfType<Class>())
+	{
+		foreach (var p in GetTreeNodes(cl).OfType<Property>())
+		{
+			if (p.DisplayName != null)
+			{
+				p.Attributes.Add(new Attribute("Display", "Name=" + ToStringLiteral(p.DisplayName)) { IsSeparated = true });
+			}
+
+			if (p.IsRequired)
+			{
+				var attr = new Attribute("Required") { IsSeparated = true };
+
+				if (p.IsRequiredMessage != null)
+					attr.Parameters.Add(string.Format("ErrorMessage=" + ToStringLiteral(p.IsRequiredMessage), p.DisplayName ?? p.Name));
+
+				p.Attributes.Add(attr);
+			}
+
+			if (p.StringLength > 0)
+			{
+				var attr = new Attribute("StringLength", p.StringLength.ToString()) { IsSeparated = true };
+
+				if (p.StringLengthMessage != null)
+					attr.Parameters.Add(string.Format("ErrorMessage=" + ToStringLiteral(p.StringLengthMessage), p.DisplayName ?? p.Name));
+
+				p.Attributes.Add(attr);
+
+//				p.Attributes.Add(
+//					new Attribute("StringLength",
+//						p.StringLength.ToString(),
+//						"ErrorMessage=" + ToStringLiteral(string.Format(
+//							"The {0} must be a string with a maximum length of {1}.",
+//							p.DisplayName ?? "field",
+//							p.StringLength)))
+//					{
+//						IsSeparated = true
+//					});
+			}
+		}
+	}
+}
+
+partial class Property
+{
+	public string DisplayName;
+	public bool   IsRequired;
+	public string IsRequiredMessage;
+	public int    StringLength;
+	public string StringLengthMessage;
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/DataModel.ttinclude b/src/Version/LinqToDB.Templates/DataModel.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..b28013d9c981ef4b05570f9207d23fbb95cd44fd
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/DataModel.ttinclude
@@ -0,0 +1,871 @@
+<#@ assembly name="System.Data"                #>
+<#@ import namespace="System.Data"             #>
+<#@ import namespace="LinqToDB.SchemaProvider" #>
+<#@ 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}>";
+
+bool     GenerateDatabaseName          = false;
+bool     GenerateConstructors          = true;
+string   DefaultConfiguration          = null;
+bool     GenerateAssociations          = true;
+bool     GenerateBackReferences        = true;
+bool     GenerateAssociationExtensions = false;
+bool     ReplaceSimilarTables          = true;
+bool     IncludeDefaultSchema          = true;
+
+Class    DataContextObject;
+
+bool PluralizeClassNames                 = false;
+bool SingularizeClassNames               = true;
+bool PluralizeDataContextPropertyNames   = true;
+bool SingularizeDataContextPropertyNames = false;
+
+bool NormalizeNames                      = true;
+
+private Func<string, bool, string> _toValidName;
+Func<string, bool, string> ToValidName
+{
+	get { return _toValidName ?? ToValidNameDefault; }
+	set { _toValidName = value; }
+}
+
+private Func<string, bool, string> _convertToCompilabl;
+Func<string, bool, string> ConvertToCompilable
+{
+	get { return _convertToCompilabl ?? ConvertToCompilableDefault; }
+	set { _convertToCompilabl = value; }
+}
+
+private Func<ForeignKey, string> _getAssociationExtensionPluralName;
+Func<ForeignKey, string> GetAssociationExtensionPluralName
+{
+	get { return _getAssociationExtensionPluralName ?? GetAssociationExtensionPluralNameDefault; }
+	set { _getAssociationExtensionPluralName = value; }
+}
+
+private Func<ForeignKey, string> _getAssociationExtensionSingularName;
+Func<ForeignKey, string> GetAssociationExtensionSinglularName
+{
+	get { return _getAssociationExtensionSingularName ?? GetAssociationExtensionSinglularNameDefault; }
+	set { _getAssociationExtensionSingularName = value; }
+}
+
+LinqToDB.SchemaProvider.GetSchemaOptions GetSchemaOptions =
+	new LinqToDB.SchemaProvider.GetSchemaOptions();
+
+LinqToDB.SqlProvider.ISqlBuilder SqlBuilder;
+
+Func<TableSchema,Table> LoadProviderSpecificTable = tableSchema => null;
+
+static Func<ColumnSchema,string>                 ConvertColumnMemberType          = (c) => c.MemberType;
+static Func<TableSchema,ColumnSchema,string>     ConvertTableColumnMemberType     = (t,c) => ConvertColumnMemberType(c);
+static Func<ProcedureSchema,ColumnSchema,string> ConvertProcedureColumnMemberType = (t,c) => ConvertColumnMemberType(c);
+
+HashSet<string> 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",     "namespace", "string"
+};
+
+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 = ToValidName(db.Database, true) + "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
+		.Where(t => !t.IsProviderSpecific)
+		.Select(t => new
+		{
+			t,
+			key = t.IsDefaultSchema ? t.TableName : t.SchemaName + "." + t.TableName,
+			table = new Table
+			{
+				TableSchema             = t,
+				IsDefaultSchema         = t.IsDefaultSchema,
+				Schema                  = t.IsDefaultSchema && !IncludeDefaultSchema || string.IsNullOrEmpty(t.SchemaName)? null : t.SchemaName,
+				BaseClass               = BaseEntityClass,
+				TableName               = t.TableName,
+				TypeName                = t.TypeName,
+				DataContextPropertyName = t.TypeName,
+				IsView                  = t.IsView,
+				IsProviderSpecific      = false,
+				Description             = t.Description,
+				Columns                 = t.Columns.ToDictionary(
+					c => c.ColumnName,
+					c => new Column
+					{
+						ColumnName      = c.ColumnName,
+						ColumnType      = c.ColumnType,
+						DataType        = "DataType." + c.DataType,
+						Length          = c.Length,
+						Precision       = c.Precision,
+						Scale           = c.Scale,
+						IsNullable      = c.IsNullable,
+						IsIdentity      = c.IsIdentity,
+						IsPrimaryKey    = c.IsPrimaryKey,
+						PrimaryKeyOrder = c.PrimaryKeyOrder,
+						MemberName      = CheckType(c.SystemType, c.MemberName),
+						TypeBuilder     = () => ConvertTableColumnMemberType(t, c),
+						SkipOnInsert    = c.SkipOnInsert,
+						SkipOnUpdate    = c.SkipOnUpdate,
+						Description     = c.Description,
+					})
+			}
+		})
+		.ToList();
+
+	if (PluralizeClassNames || SingularizeClassNames)
+	{
+		var foundNames = new HashSet<string>(tables.Select(t => t.table.Schema + '.' + 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(t.table.Schema + '.' + newName))
+				{
+					t.table.TypeName = newName;
+					foundNames.Add(t.table.Schema + '.' + newName);
+				}
+			}
+		}
+	}
+
+	if (PluralizeDataContextPropertyNames || SingularizeDataContextPropertyNames)
+	{
+		var foundNames = new HashSet<string>(tables.Select(t => t.table.Schema + '.' + 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(t.table.Schema + '.' + newName))
+				{
+					t.table.DataContextPropertyName = newName;
+					foundNames.Add(t.table.Schema + '.' + newName);
+				}
+			}
+		}
+	}
+
+	tables.AddRange(db.Tables
+		.Where(t => t.IsProviderSpecific)
+		.Select(t => new
+		{
+			t,
+			key = t.IsDefaultSchema ? t.TableName : t.SchemaName + "." + t.TableName,
+			table = LoadProviderSpecificTable(t)
+		})
+		.Where(t => t.table != null));
+
+	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.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
+		.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                = ToValidName(p.MemberName, true),
+				IsFunction          = p.IsFunction,
+				IsTableFunction     = p.IsTableFunction,
+				IsAggregateFunction = p.IsAggregateFunction,
+				IsDefaultSchema     = p.IsDefaultSchema,
+				IsLoaded            = p.IsLoaded,
+				ResultTable         = p.ResultTable == null ? null :
+					new Table
+					{
+						TypeName = ToValidName(
+							PluralizeClassNames   ? ToPlural  (p.ResultTable.TypeName) :
+							SingularizeClassNames ? ToSingular(p.ResultTable.TypeName) : p.ResultTable.TypeName, true),
+						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      = CheckColumnName(CheckType(c.SystemType, c.MemberName)),
+								TypeBuilder     = () => ConvertProcedureColumnMemberType(p, c),
+								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 = CheckParameterName(CheckType(pr.SystemType, 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;
+}
+
+string CheckColumnName(string memberName)
+{
+	if (string.IsNullOrEmpty(memberName))
+		memberName = "Empty";
+	else
+	{
+		memberName = memberName
+			.Replace("%", "Percent")
+			.Replace(">", "Greater")
+			.Replace("<", "Lower")
+			.Replace("+", "Plus")
+			.Replace('(', '_')
+			.Replace(')', '_')
+			.Replace('-', '_')
+			.Replace('|', '_')
+			.Replace(',', '_')
+			.Replace('"', '_')
+			.Replace("'", "_")
+			.Replace(".", "_")
+			.Replace("\u00A3", "Pound");
+
+		if (KeyWords.Contains(memberName))
+			memberName = "@" + memberName;
+	}
+	return memberName;
+}
+
+string CheckParameterName(string parameterName)
+{
+	var invalidParameterNames = new List<string>
+	{
+		"@DataType"
+	};
+
+	var result = parameterName;
+	while (invalidParameterNames.Contains(result))
+	{
+		result = result + "_";
+	}
+	return result;
+}
+
+Action AfterLoadMetadata = () => {};
+
+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");
+
+	foreach (var t in Tables.Values)
+	{
+		if (KeyWords.Contains(t.TypeName))
+			t.TypeName = "@" + t.TypeName;
+
+		if (KeyWords.Contains(t.DataContextPropertyName))
+			t.DataContextPropertyName = "@" + t.DataContextPropertyName;
+
+		t.TypeName                = ConvertToCompilable(t.TypeName,                true);
+		t.DataContextPropertyName = ConvertToCompilable(t.DataContextPropertyName, true);
+
+		foreach (var col in t.Columns.Values)
+		{
+			if (KeyWords.Contains(col.MemberName))
+				col.MemberName = "@" + col.MemberName;
+
+			col.MemberName = ConvertToCompilable(col.MemberName, true);
+
+			if (col.MemberName == t.TypeName)
+				col.MemberName += "_Column";
+		}
+
+		foreach (var fk in t.ForeignKeys.Values)
+		{
+			if (KeyWords.Contains(fk.MemberName))
+				fk.MemberName = "@" + fk.MemberName;
+
+			fk.MemberName = ConvertToCompilable(fk.MemberName, true);
+
+			if (fk.MemberName == t.TypeName)
+				fk.MemberName += "_FK";
+		}
+	}
+
+	foreach (var t in Tables.Values)
+	{
+		var hasDuplicates = t.Columns.Values
+				.Select(c => c.MemberName)
+				.Concat(t.ForeignKeys.Values.Select(f => f.MemberName))
+				.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(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(t.ForeignKeys.Values.Select(fk => fk.MemberName));
+
+				col.MemberName = SuggestNoDuplicate(mayDuplicate, col.MemberName, null);
+			}
+		}
+	}
+
+	foreach (var proc in Procedures.Values)
+	{
+	    proc.Name = ConvertToCompilable(proc.Name, false);
+
+		if (KeyWords.Contains(proc.Name))
+			proc.Name = "@" + proc.Name;
+
+		foreach (var param in proc.ProcParameters)
+		{
+			if (KeyWords.Contains(param.ParameterName))
+				param.ParameterName = ConvertToCompilable("@" + param.ParameterName, true);
+		}
+	}
+
+	AfterLoadMetadata();
+}
+
+string SuggestNoDuplicate(IEnumerable<string> currentNames, string newName, string prefix)
+{
+	var names = new HashSet<string>(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 =
+		from c in name
+		select char.IsLetterOrDigit(c) || c == '@' ? c : '_';
+
+	return ToValidName(new string(query.ToArray()), mayRemoveUnderscore);
+}
+
+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.");
+}
+
+
+public TableContext SetTable(string tableName,
+	string TypeName                = null,
+	string DataContextPropertyName = null)
+{
+	var ctx = new TableContext { Transformation = this, TableName = tableName };
+
+	if (TypeName != null || DataContextPropertyName != null)
+	{
+		var t = GetTable(tableName);
+
+		if (TypeName                != null) t.TypeName                = TypeName;
+		if (DataContextPropertyName != null) t.DataContextPropertyName = DataContextPropertyName;
+	}
+
+	return ctx;
+}
+
+public class TableContext
+{
+	public GeneratedTextTransformation Transformation;
+	public string                      TableName;
+
+	public TableContext Column(string columnName,
+		string MemberName  = null,
+		string Type        = null,
+		bool?  IsNullable  = null,
+		string Conditional = null)
+	{
+		var c = Transformation.GetColumn(TableName, columnName);
+
+		if (MemberName  != null) c.MemberName  = MemberName;
+		if (Type        != null) c.TypeBuilder = () => Type;
+		if (IsNullable  != null) c.IsNullable  = IsNullable.Value;
+		if (Conditional != null) c.Conditional = Conditional;
+
+		return this;
+	}
+
+	public TableContext FK(string fkName,
+		string           MemberName      = null,
+		AssociationType? AssociationType = null,
+		bool?            CanBeNull       = null)
+	{
+		var c = Transformation.GetFK(TableName, fkName);
+
+		if (MemberName      != null) c.MemberName      = MemberName;
+		if (AssociationType != null) c.AssociationType = AssociationType.Value;
+		if (CanBeNull       != null) c.CanBeNull       = CanBeNull.Value;
+
+		return this;
+	}
+}
+
+
+Dictionary<string,Table>     Tables     = new Dictionary<string,Table>    ();
+Dictionary<string,Procedure> Procedures = new Dictionary<string,Procedure>();
+
+public partial class Table : Class
+{
+	public TableSchema TableSchema             { get; set; }
+	public string      Schema                  { get; set; }
+	public string      TableName               { get; set; }
+	public string      DataContextPropertyName { get; set; }
+	public MemberBase  DataContextProperty     { get; set; }
+	public bool        IsView                  { get; set; }
+	public bool        IsProviderSpecific      { get; set; }
+	public bool        IsDefaultSchema         { get; set; }
+	public string      Description             { get; set; }
+	public string      AliasPropertyName       { get; set; }
+	public string      AliasTypeName           { get; set; }
+	public string      TypePrefix              { 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 string    DataType;
+	public long?     Length;
+	public int?      Precision;
+	public int?      Scale;
+	public DbType    DbType;
+	public string    Description;
+	public bool      IsPrimaryKey;
+	public int       PrimaryKeyOrder;
+	public bool      SkipOnUpdate;
+	public bool      SkipOnInsert;
+	public bool      IsDuplicateOrEmpty;
+	public bool      IsDiscriminator;
+	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   IsAggregateFunction { get; set; }
+	public bool   IsDefaultSchema     { get; set; }
+	public bool   IsLoaded            { 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 long?    Size          { get; set; }
+
+	public string   ParameterName { get; set; }
+	public string   ParameterType { get; set; }
+	public Type     SystemType    { get; set; }
+	public string   DataType      { get; set; }
+}
+
+private int _counter = 0;
+
+string ToValidNameDefault(string name, bool mayRemoveUnderscore)
+{
+	if (NormalizeNames && mayRemoveUnderscore && name.Contains("_"))
+	{
+		name = SplitAndJoin(name, "", '_');
+	}
+
+	if (name.Contains("."))
+	{
+		name = SplitAndJoin(name, "", '.');
+	}
+
+	if (name.Length > 0 && char.IsDigit(name[0]))
+		name = "_" + name;
+
+	if (string.IsNullOrEmpty(name))
+		name = "_" + _counter++;
+
+	if (NormalizeNames)
+	{
+		name = char.ToUpper(name[0]) + name.Substring(1);
+	}
+
+	return name;
+}
+
+static string SplitAndJoin(string value, string join, params char[] split)
+{
+	var ss = value.Split(split, StringSplitOptions.RemoveEmptyEntries)
+		.Select(s => char.ToUpper(s[0]) + (s.Substring(1).All(char.IsUpper) ? s.Substring(1).ToLower() : s.Substring(1)));
+
+	return string.Join(join, ss.ToArray());
+}
+
+private string GetAssociationExtensionSinglularNameDefault(ForeignKey key)
+{
+	return ToSingular(key.Name);
+}
+
+private string GetAssociationExtensionPluralNameDefault(ForeignKey key)
+{
+	return ToPlural(ToSingular(key.Name));
+}
+
+#>
diff --git a/src/Version/LinqToDB.Templates/EditableObject.ttinclude b/src/Version/LinqToDB.Templates/EditableObject.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..e9506c2a27020962e7fe38b07be4972479478707
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/EditableObject.ttinclude
@@ -0,0 +1,250 @@
+<#
+	{
+		var beforeGenerateModel = BeforeGenerateModel;
+		BeforeGenerateModel = () =>
+		{
+			EditableObjectImpl();
+			beforeGenerateModel();
+		};
+
+		SetPropertyValueAction += (obj,prop,val) =>
+		{
+			if (prop == "IsEditable")
+				obj.IsEditable = (bool)val;
+		};
+	}
+#>
+<#+
+void EditableObjectImpl()
+{
+	foreach (Property prop in GetTreeNodes(Model).OfType<Property>().Where(p => p.IsEditable).ToList())
+	{
+		SetPropertyValue(prop, "IsNotifying", true);
+
+		List<IClassMember> parentMembers;
+
+		MemberGroup gr = null;
+
+		if (prop.Parent is Class)
+		{
+			var parent = (Class)prop.Parent;
+			parentMembers = parent.Members;
+		}
+		else
+		{
+			var parent = (MemberGroup)prop.Parent;
+			parentMembers = parent.Members;
+
+			parent.IsCompact = false;
+		}
+
+		var name = prop.Name.Trim();
+		var type = prop.BuildType().Trim();
+
+		if (gr == null)
+		{
+			gr = new MemberGroup
+			{
+				Region          = name + " : " + type,
+				Members         = { prop },
+				IsPropertyGroup = true,
+			};
+
+			var index = parentMembers.IndexOf(prop);
+
+			parentMembers.RemoveAt(index);
+			parentMembers.Insert  (index, gr);
+		}
+
+		var originalField = new Field(() => type, "_original" + name)
+		{
+			AccessModifier       = AccessModifier.Private,
+			InsertBlankLineAfter = false,
+		};
+
+		gr.Members.Insert(0, originalField);
+
+		var currentField = new Field(() => type, " _current" + name)
+		{
+			AccessModifier       = AccessModifier.Private,
+			InsertBlankLineAfter = false,
+		};
+
+		if (prop.InitValue != null)
+			currentField.InitValue = prop.InitValue;
+
+		gr.Members.Insert(0, currentField);
+
+		prop.Name        = "         " + name;
+		prop.TypeBuilder = () => " " + type;
+		prop.IsAuto      = false;
+
+		if (prop.HasGetter) prop.GetBodyBuilders.Add(() => new [] { "return " + currentField.Name.Trim() + ";" });
+		if (prop.HasSetter) prop.SetBodyBuilders.Add(() => new [] { currentField.Name.Trim() + " = value;" });
+
+		var ac = new Method  (() => "void", "Accept" + name + "Changes", null, () => new[] { string.Format("_original{0} = _current{0};", name) });
+		var rc = new Method  (() => "void", "Reject" + name + "Changes", null, () => new[] { string.Format("{0} = _original{0};", name) });
+		var id = new Property(() => "bool", "Is" + name + "Dirty")
+			.InitGetter(() => new [] { string.Format(prop.IsDirtyText, "_current" + name, "_original" + name) });
+
+		gr.Members.Add(new MemberGroup
+		{
+			Region  = "EditableObject support",
+			Members = { ac, rc, id },
+		});
+
+		prop.Parent.SetTree();
+	}
+
+	foreach (Class cl in GetTreeNodes(Model).OfType<Class>())
+	{
+		var props = GetTreeNodes(cl).OfType<Property>().Where(p => p.IsEditable).ToList();
+
+		if (props.Count > 0)
+		{
+			if (props.Any(p => p.IsEditable))
+			{
+				var ctor = GetTreeNodes(cl)
+					.OfType<Method>()
+					.FirstOrDefault(m => m.Name == cl.Name && m.ParameterBuilders.Count == 0);
+
+				if (ctor == null)
+				{
+					ctor = new Method(null, cl.Name);
+					cl.Members.Insert(0, ctor);
+				}
+
+				ctor.BodyBuilders.Add(() => new [] { "AcceptChanges();" });
+			}
+
+			var maxLen = props.Max(p => p.Name.Trim().Length);
+
+			var ac = new Method(() => "void", "AcceptChanges") { IsVirtual = true };
+			var rc = new Method(() => "void", "RejectChanges") { IsVirtual = true };
+			var id = new Property(() => "bool", "IsDirty") { IsAuto = false, HasSetter = false, IsVirtual = true };
+
+			ac.BodyBuilders.Add(() => new []
+			{
+				"BeforeAcceptChanges();",
+				""
+			});
+			rc.BodyBuilders.Add(() => new []
+			{
+				"BeforeRejectChanges();",
+				""
+			});
+			id.GetBodyBuilders.Add(() => new [] { "return" });
+
+			foreach (var p in props)
+			{
+				var name = p.Name.Trim();
+
+				ac.BodyBuilders.Add(() => new [] { string.Format("Accept{0}Changes();", name) });
+				rc.BodyBuilders.Add(() => new [] { string.Format("Reject{0}Changes();", name) });
+				id.GetBodyBuilders.Add(() => new [] { string.Format("\tIs{0}Dirty{1} ||", name, LenDiff(maxLen, name)) });
+			}
+
+			ac.BodyBuilders.Add(() => new[]
+			{
+				"",
+				"AfterAcceptChanges();"
+			});
+			rc.BodyBuilders.Add(() => new[]
+			{
+				"",
+				"AfterRejectChanges();"
+			});
+			var getBody = id.BuildGetBody().ToArray();
+			getBody[getBody.Length - 1] = getBody[getBody.Length - 1].Trim(' ' , '|') + ";";
+			id.GetBodyBuilders.Clear();
+			id.GetBodyBuilders.Add(() => getBody);
+
+			cl.Members.Add(new MemberGroup
+			{
+				Region  = "EditableObject support",
+				Members =
+				{
+					new MemberGroup
+					{
+						IsCompact = true,
+						Members   =
+						{
+							new Method(() => "void", "BeforeAcceptChanges") { AccessModifier = AccessModifier.Partial },
+							new Method(() => "void", "AfterAcceptChanges")  { AccessModifier = AccessModifier.Partial },
+						}
+					},
+					ac,
+					new MemberGroup
+					{
+						IsCompact = true,
+						Members   =
+						{
+							new Method(() => "void", "BeforeRejectChanges") { AccessModifier = AccessModifier.Partial },
+							new Method(() => "void", "AfterRejectChanges")  { AccessModifier = AccessModifier.Partial },
+						}
+					},
+					rc,
+					id
+				},
+			});
+
+			if (!cl.Interfaces.Contains("IEditableObject"))
+			{
+				if (!Model.Usings.Contains("System.ComponentModel"))
+					Model.Usings.Add("System.ComponentModel");
+
+				cl.Interfaces.Add("IEditableObject");
+
+				cl.Members.Add(new MemberGroup
+				{
+					Region  = "IEditableObject support",
+					Members =
+					{
+						new MemberGroup
+						{
+							IsCompact = true,
+							Members   =
+							{
+								new Field   (() => "bool", "_isEditing") { AccessModifier = AccessModifier.Private },
+								new Property(() => "bool", " IsEditing").InitGetter(() => new [] { "_isEditing" }),
+							}
+						},
+						new MemberGroup
+						{
+							IsCompact = true,
+							Members   =
+							{
+								new Method(() => "void", "BeginEdit",  null, () => new[] { "AcceptChanges();", "_isEditing = true;"   }) { IsVirtual = true },
+								new Method(() => "void", "CancelEdit", null, () => new[] { "_isEditing = false;", "RejectChanges();", }) { IsVirtual = true },
+								new Method(() => "void", "EndEdit",    null, () => new[] { "_isEditing = false;", "AcceptChanges();", }) { IsVirtual = true },
+							}
+						},
+					}
+				});
+			}
+		}
+
+		cl.SetTree();
+	}
+}
+
+partial class Property
+{
+	public bool   IsEditable;
+	public string IsDirtyText = "{0} != {1}";
+}
+
+class EditableProperty : Property
+{
+	public EditableProperty()
+	{
+		IsEditable = true;
+	}
+
+	public EditableProperty(string type, string name)
+		: base(() => type, name, null, null)
+	{
+		IsEditable = true;
+	}
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/Humanizer.ttinclude b/src/Version/LinqToDB.Templates/Humanizer.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..17be0916cc74e01a29558a7cd6013fe567aa1409
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/Humanizer.ttinclude
@@ -0,0 +1,15 @@
+<#
+/*
+To use this extension you should:
+1) Reference Humanizer NuGet package into your project
+2) Include Humanizer.ttinclude
+3) Reference assembly like <_#@ assembly name="$(SolutionDir)\packages\Humanizer.Core.2.2.0\lib\netstandard1.0\Humanizer.dll" #_>
+*/
+#>
+<#@ import namespace="Humanizer" #>
+<#
+	NormalizeNames = true;
+	ToPlural       = s => s.Pluralize  (inputIsKnownToBeSingular: false);
+	ToSingular     = s => s.Singularize(inputIsKnownToBePlural:   false);
+	ToValidName    = (s, r) => s.Pascalize();
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Access.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Access.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..ebabf0fb9054ec5336c069f94297ed81ea95e1f4
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Access.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Access.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Access.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Access.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..806e50298187b6c2bccde49d7a3ee4f52673b8d1
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Access.ttinclude
@@ -0,0 +1,26 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#+
+LinqToDB.Data.DataConnection GetAccessConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.Access.AccessTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetAccessConnection(string path, string database)
+{
+	return GetAccessConnection(string.Format(
+		"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Locale Identifier=1033;Jet OLEDB:Engine Type=5;Persist Security Info=True",
+		System.IO.Path.Combine(path, database)));
+}
+
+void LoadAccessMetadata(string connectionString)
+{
+	using (var dataConnection = GetAccessConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadAccessMetadata(string path, string database)
+{
+	using(var dataConnection = GetAccessConnection(path, database))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.DB2.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.DB2.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..c9aba99f74df410d0f2677bffa35d976f6d0c045
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.DB2.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.DB2.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.DB2.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.DB2.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..12a174244be63278b41ce4f1e58fa8a4c0df8220
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.DB2.ttinclude
@@ -0,0 +1,24 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#+
+LinqToDB.Data.DataConnection GetDB2Connection(string connectionString, LinqToDB.DataProvider.DB2.DB2Version version = LinqToDB.DataProvider.DB2.DB2Version.LUW)
+{
+	return LinqToDB.DataProvider.DB2.DB2Tools.CreateDataConnection(connectionString, version);
+}
+
+LinqToDB.Data.DataConnection GetDB2Connection(string server, string port, string database, string uid, string password)
+{
+	return GetDB2Connection(string.Format("Server={0}:{1};Database={2};UID={3};PWD={4};", server, port, database, uid, password));
+}
+
+void LoadDB2Metadata(string connectionString)
+{
+	using (var dataConnection = GetDB2Connection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadDB2Metadata(string server, string port, string database, string uid, string password)
+{
+	using (var dataConnection = GetDB2Connection(server, port, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Firebird.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Firebird.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..8c5568ddef69c280d079bd03b0a4a0643d0f0947
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Firebird.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4FirebirdToolsDirectory)FirebirdSql.Data.FirebirdClient.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Firebird.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Firebird.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Firebird.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..533dbdf01c0bf77e4373bffceea3e978322630ff
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Firebird.ttinclude
@@ -0,0 +1,71 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	LinqToDB.DataProvider.Firebird.FirebirdTools.ResolveFirebird(
+		typeof(FirebirdSql.Data.FirebirdClient.FbConnection).Assembly);
+
+	{
+		var afterLoadMetadata = AfterLoadMetadata;
+		AfterLoadMetadata = () =>
+		{
+			afterLoadMetadata();
+			CheckNameCasing();
+		};
+	}
+#>
+<#+
+void CheckNameCasing()
+{
+	foreach (var t in Tables.Values)
+	{
+		var name = t.TableName;
+
+		if (!name.StartsWith("\""))
+			if (name.StartsWith("_") || name.Any(c => char.IsLower(c) || char.IsWhiteSpace(c)))
+				t.TableName = "\"" + name + "\"";
+
+		foreach (var col in t.Columns.Values)
+		{
+			name = col.ColumnName;
+
+			if (!name.StartsWith("\""))
+				if (name.StartsWith("_") || name.Any(c => char.IsLower(c) || char.IsWhiteSpace(c)))
+					col.ColumnName = "\"" + name + "\"";
+		}
+	}
+}
+
+LinqToDB.Data.DataConnection GetFirebirdConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.Firebird.FirebirdTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetFirebirdConnection(string server, string database)
+{
+	return GetFirebirdConnection(server, database, "SYSDBA", "masterkey");
+}
+
+LinqToDB.Data.DataConnection GetFirebirdConnection(string server, string database, string uid, string password)
+{
+	return GetFirebirdConnection(string.Format(
+		"DataSource={0};Database={1};User Id={2};Password={3}",
+		server, database, uid, password));
+}
+
+void LoadFirebirdMetadata(string connectionString)
+{
+	using (var dataConnection = GetFirebirdConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadFirebirdMetadata(string server, string database, string uid, string password)
+{
+	using (var dataConnection = GetFirebirdConnection(server, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+
+void LoadFirebirdMetadata(string server, string database)
+{
+	using (var dataConnection = GetFirebirdConnection(server, database))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Informix.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Informix.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..ffe6b4aaecbd4307757ded267dc29884ea397da6
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Informix.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Informix.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Informix.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Informix.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..ce007c248db35929125d254f5e511bd3698664a5
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Informix.ttinclude
@@ -0,0 +1,24 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#+
+LinqToDB.Data.DataConnection GetInformixConnection(string connectionString)
+{
+	return new LinqToDB.Data.DataConnection(new LinqToDB.DataProvider.Informix.InformixDataProvider(), connectionString);
+}
+
+LinqToDB.Data.DataConnection GetInformixConnection(string host, string port, string server, string database, string uid, string password)
+{
+	return GetInformixConnection(string.Format("Host={0};Service={1};Server={2};Protocol=onsoctcp;Database={3};UID={4};PWD={5}", host, port, server, database, uid, password));
+}
+
+void LoadInformixMetadata(string connectionString)
+{
+	using (var dataConnection = GetInformixConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadInformixMetadata(string host, string port, string server, string database, string uid, string password)
+{
+	using (var dataConnection = GetInformixConnection(host, port, server, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.MySql.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.MySql.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..023871292b7d43e2e12da1981d227ac7bdb2af7e
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.MySql.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4MySqlToolsDirectory)MySql.Data.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.MySql.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.MySql.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.MySql.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..fd93d3e9c686f3b52e7d2064a25c1aefd6a6dac5
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.MySql.ttinclude
@@ -0,0 +1,30 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	LinqToDB.DataProvider.MySql.MySqlTools.ResolveMySql(
+		typeof(MySql.Data.MySqlClient.MySqlConnection).Assembly);
+#>
+<#+
+LinqToDB.Data.DataConnection GetMySqlConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.MySql.MySqlTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetMySqlConnection(string server, string database, string uid, string password, int port=3306)
+{
+	return GetMySqlConnection(string.Format(
+		"Server={0};Port={4};Database={1};Uid={2};Pwd={3};charset=utf8;",
+		server, database, uid, password,port));
+}
+
+void LoadMySqlMetadata(string connectionString)
+{
+	using (var dataConnection = GetMySqlConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadMySqlMetadata(string server, string database, string uid, string password,int port=3306)
+{
+	using (var dataConnection = GetMySqlConnection(server, database, uid, password,port))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Managed.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Managed.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..4b4be38b605c7e394bbcea45db70e8d5ee78e2da
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Managed.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4OracleToolsDirectory)Oracle.ManagedDataAccess.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Oracle.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..4b4be38b605c7e394bbcea45db70e8d5ee78e2da
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4OracleToolsDirectory)Oracle.ManagedDataAccess.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Oracle.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Oracle.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..ff6f6725137777d95a6bbb3c76d8d47672439a35
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.ttinclude
@@ -0,0 +1,29 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	LinqToDB.DataProvider.Oracle.OracleTools.AssemblyName = "Oracle.ManagedDataAccess";
+	LinqToDB.DataProvider.Oracle.OracleTools.ResolveOracle(
+		typeof(Oracle.ManagedDataAccess.Client.OracleConnection).Assembly);
+#><#+
+LinqToDB.Data.DataConnection GetOracleConnection(string connectionString)
+{
+	//return LinqToDB.DataProvider.Oracle.OracleTools.CreateDataConnection(connectionString);
+	return new LinqToDB.Data.DataConnection(new LinqToDB.DataProvider.Oracle.OracleDataProvider("OracleManaged"), connectionString);
+}
+
+LinqToDB.Data.DataConnection GetOracleConnection(string server, string port, string database, string uid, string password)
+{
+	return GetOracleConnection(string.Format("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1}))(CONNECT_DATA=(SERVICE_NAME={2})));User Id={3};Password={4};", server, port, database, uid, password));
+}
+
+void LoadOracleMetadata(string connectionString)
+{
+	using (var dataConnection = GetOracleConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadOracleMetadata(string server, string port, string database, string uid, string password)
+{
+	using (var dataConnection = GetOracleConnection(server, port, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x64.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x64.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..4b4be38b605c7e394bbcea45db70e8d5ee78e2da
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x64.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4OracleToolsDirectory)Oracle.ManagedDataAccess.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Oracle.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x86.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x86.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..4b4be38b605c7e394bbcea45db70e8d5ee78e2da
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Oracle.x86.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4OracleToolsDirectory)Oracle.ManagedDataAccess.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Oracle.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..d23123133419d046323c415e8806e8e880714ed4
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.Tools.ttinclude
@@ -0,0 +1,4 @@
+<#@ assembly name="$(LinqToDBT4PostgreSQLToolsDirectory)Npgsql.dll" #>
+<#@ assembly name="$(LinqToDBT4PostgreSQLToolsDirectory)System.Threading.Tasks.Extensions.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.PostgreSQL.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..7fae75f29bb430e61978db6845a9be11c3b612b6
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.PostgreSQL.ttinclude
@@ -0,0 +1,144 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	LinqToDB.DataProvider.PostgreSQL.PostgreSQLTools.ResolvePostgreSQL(
+		typeof(Npgsql.NpgsqlConnection).Assembly);
+
+	{
+		var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel;
+		BeforeGenerateLinqToDBModel = () =>
+		{
+			beforeGenerateLinqToDBModel();
+			SetCaseSensitiveNames();
+
+			FixTableFunctions();
+			FixRecordResultFunctions();
+			FixVoidFunctions();
+			FixFunctionNames();
+		};
+	}
+#>
+<#+
+bool GenerateCaseSensitiveNames = false; // Defines whether to generate case sensitive or insensitive names
+
+// functions with multiple out parameters implemented by pgsql as functions with input parameters that return record with
+// value for each output parameter so we need to move out parameters to result value class field and map
+// record, returned by npgsql provider as object[], to this class
+// exception: functions with only one out parameter treat it as return parameter
+void FixRecordResultFunctions()
+{
+	var initMappingSchema = new Method(() => "void", "InitMappingSchema") { AccessModifier = AccessModifier.Partial };
+	DataContextObject.Members.Add(initMappingSchema);
+	foreach (var proc in Procedures.Values
+		.Where(p => p.IsFunction && !p.IsAggregateFunction && !p.IsTableFunction && p.ProcParameters.Any(pr => pr.IsOut)))
+	{
+		if (proc.ProcParameters.Count(pr => pr.IsOut) > 1)
+		{
+			var result = new Class(SchemaProviderBase.ToValidName(proc.ProcedureName + "Result"));
+			Model.Types.Add(result);
+
+			proc.ProcParameters.Add(new Parameter()
+			{
+				IsResult      = true,
+				ParameterType = result.Name
+			});
+
+			var mappings = new List<string>();
+			foreach (var outParam in proc.ProcParameters.Where(_ => _.IsOut))
+			{
+				result.Members.Add(new Property(() => outParam.ParameterType, outParam.ParameterName, null, null));
+				mappings.Add($"{outParam.ParameterName} = ({outParam.ParameterType})tuple[{mappings.Count}]");
+
+				if (outParam.IsIn)
+					outParam.IsOut = false;
+			}
+
+			proc.ProcParameters = proc.ProcParameters.Where(_ => !_.IsOut).ToList();
+
+			initMappingSchema.BodyBuilders.Add(() => new [] { $"MappingSchema.SetConvertExpression<object[], {result.Name}>(tuple => new {result.Name}() {{ {string.Join(", ", mappings)} }});" });
+		}
+		else // one parameter
+		{
+			var param = proc.ProcParameters.Single(_ => _.IsOut);
+			proc.ProcParameters.Remove(param);
+			proc.ProcParameters.Add(new Parameter()
+			{
+				IsResult      = true,
+				ParameterType = param.ParameterType
+			});
+		}
+	}
+}
+
+void FixFunctionNames()
+{
+	foreach (var proc in Procedures.Values)
+	{
+		if (proc.ProcedureName.Any(char.IsUpper))
+			proc.ProcedureName = "\"" + proc.ProcedureName + "\"";
+	}
+}
+
+void FixTableFunctions()
+{
+	foreach (var proc in Procedures.Values
+		.Where(p => p.IsTableFunction && p.ProcParameters.Any(pr => pr.IsOut)))
+	{
+		proc.ProcParameters = proc.ProcParameters.Where(pr => !pr.IsOut).ToList();
+	}
+}
+
+void FixVoidFunctions()
+{
+	// generated functions should return object for void-typed functions
+	foreach (var proc in Procedures.Values
+		.Where(p => p.IsFunction/* && !p.IsAggregateFunction*/ && !p.IsTableFunction && !p.ProcParameters.Any(pr => pr.IsResult)))
+	{
+		proc.ProcParameters.Add(new Parameter()
+		{
+			IsResult      = true,
+			ParameterType = "object",
+			SystemType    = typeof(object)
+		});
+	}
+}
+
+void SetCaseSensitiveNames()
+{
+	if (GenerateCaseSensitiveNames)
+	{
+		foreach (var t in Tables.Values)
+		{
+			if (t.TableName.Any(char.IsUpper))
+				t.TableName = "\"" + t.TableName + "\"";
+
+			foreach (var c in t.Columns.Values)
+			{
+				if (c.ColumnName.Any(char.IsUpper))
+					c.ColumnName = "\"" + c.ColumnName + "\"";
+			}
+		}
+	}
+}
+
+LinqToDB.Data.DataConnection GetPostgreSQLConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.PostgreSQL.PostgreSQLTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetPostgreSQLConnection(string server, string port, string database, string uid, string password)
+{
+	return GetPostgreSQLConnection(string.Format(@"Server={0};Port={1};Database={2};User Id={3};Password={4};Pooling=true;MinPoolSize=10;MaxPoolSize=100;", server, port, database, uid, password));
+}
+
+void LoadPostgreSQLMetadata(string connectionString)
+{
+	using (var dataConnection = GetPostgreSQLConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadPostgreSQLMetadata(string server, string port, string database, string uid, string password)
+{
+	using (var dataConnection = GetPostgreSQLConnection(server, port, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SQLite.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SQLite.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..71eb281790ae04b858c71883c55bbd90241a2d3b
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SQLite.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4SQLiteToolsDirectory)System.Data.SQLite.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.SQLite.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SQLite.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SQLite.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..1b7e65c09fbd04492d059f4e1081da50fb5ce787
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SQLite.ttinclude
@@ -0,0 +1,44 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	LinqToDB.DataProvider.SQLite.SQLiteTools.ResolveSQLite(typeof(System.Data.SQLite.SQLiteConnection).Assembly);
+
+	{
+		var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel;
+		BeforeGenerateLinqToDBModel = () =>
+		{
+			ConvertSQLiteMetadata();
+			beforeGenerateLinqToDBModel();
+		};
+	}
+#>
+<#+
+void ConvertSQLiteMetadata()
+{
+	foreach (var t in Tables.Values)
+		foreach (var fk in t.ForeignKeys.Values)
+			if (fk.MemberName.Length == 0 || char.IsDigit(fk.MemberName[0]))
+				fk.MemberName = "FK_" + fk.MemberName;
+}
+
+LinqToDB.Data.DataConnection GetSQLiteConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.SQLite.SQLiteTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetSQLiteConnection(string path, string database)
+{
+	return GetSQLiteConnection(string.Format("Data Source={0}", System.IO.Path.Combine(path, database)));
+}
+
+void LoadSQLiteMetadata(string connectionString)
+{
+	using (var dataConnection = GetSQLiteConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadSQLiteMetadata(string path, string database)
+{
+	using (var dataConnection = GetSQLiteConnection(path, database))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SapHana.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SapHana.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..9d7fb847f993fc7058c09a1b629d089de1f309f8
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SapHana.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.SapHana.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SapHana.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SapHana.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..28ce34ddfabd8c59e6e5886063e742d75bcaab52
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SapHana.ttinclude
@@ -0,0 +1,106 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#@ import namespace="LinqToDB.DataProvider.SapHana"   #>
+<#
+	Model.Usings.Add("LinqToDB.DataProvider.SapHana");
+	Model.Usings.Add("System.Reflection");
+
+	GenerateProviderSpecificTable = t =>
+	{
+		var method = new Method(
+			() => string.Format("ITable<{0}>", t.TypeName),
+			t.DataContextPropertyName,
+			t.Parameters.Select(p => (Func<string>)(() => p.ParameterType + " " + p.ParameterName)),
+			() => new []
+			{
+				String.Concat("return GetTable<",t.TypeName,">(this, (MethodInfo) MethodBase.GetCurrentMethod(),"),
+				String.Join(",", t.Parameters.Select(p => p.ParameterName)),
+				");"
+			});
+
+		method.Attributes.Add(new Attribute("CalculationViewInputParametersExpression", new string[] {}));
+		return method;
+	};
+
+	LoadProviderSpecificTable = t =>
+	{
+		var v = t as ViewWithParametersTableSchema;
+		return 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,
+				IsProviderSpecific      = true,
+				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),
+					TypeBuilder     = () => c.MemberType,
+					SkipOnInsert    = c.SkipOnInsert,
+					SkipOnUpdate    = c.SkipOnUpdate,
+					Description     = c.Description,
+				}),
+				Parameters = v.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()
+			};
+	};
+#>
+<#+
+	public partial class Table
+	{
+		public List<Parameter> Parameters;
+	}
+
+	LinqToDB.Data.DataConnection GetSapHanaConnection(string connectionString)
+	{
+		return LinqToDB.DataProvider.SapHana.SapHanaTools.CreateDataConnection(connectionString);
+	}
+
+	LinqToDB.Data.DataConnection GetSapHanaConnection(string server, string schema, string uid, string password)
+	{
+		return GetSapHanaConnection(string.Format("Server={0};Current Schema={1};UserID={2};Password={3};", server, schema, uid, password));
+	}
+
+	void LoadSapHanaMetadata(DataConnection dataConnection)
+	{
+		LoadMetadata(dataConnection);
+	}
+
+	void LoadSapHanaMetadata(string connectionString)
+	{
+		using (var dataConnection = GetSapHanaConnection(connectionString))
+			LoadMetadata(dataConnection);
+	}
+
+	void LoadSapHanaMetadata(string server, string schema, string uid, string password)
+	{
+		using (var dataConnection = GetSapHanaConnection(server, schema, uid, password))
+			LoadMetadata(dataConnection);
+	}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..208440acd9184e941519a7235267659aeea40c00
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.SqlCe.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..7f4a3ebe52ec0062b5300de028011fa6f06726ca
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlCe.ttinclude
@@ -0,0 +1,24 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#+
+LinqToDB.Data.DataConnection GetSqlCeConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.SqlCe.SqlCeTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetSqlCeConnection(string path, string database)
+{
+	return GetSqlCeConnection(string.Format("Data Source={0}", System.IO.Path.Combine(path, database)));
+}
+
+void LoadSqlCeMetadata(string connectionString)
+{
+	using (var dataConnection = GetSqlCeConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadSqlCeMetadata(string path, string database)
+{
+	using (var dataConnection = GetSqlCeConnection(path, database))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..05a8e66ec1169fb6519f94ac9ddb65e45e26cb44
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.Tools.ttinclude
@@ -0,0 +1,3 @@
+<#@ assembly name="$(LinqToDBT4SqlServerToolsDirectory)Microsoft.SqlServer.Types.dll" #>
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.SqlServer.SqlTypes.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..cd971c366743fde5382c8f8ffaa09ec91e7d57b8
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.SqlTypes.ttinclude
@@ -0,0 +1,5 @@
+<#@ include file="LinqToDB.SqlServer.ttinclude" #>
+<#
+	LinqToDB.DataProvider.SqlServer.SqlServerTools.ResolveSqlTypes(
+		typeof(Microsoft.SqlServer.Types.SqlGeography).Assembly);
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..fc678e10b2c02405a263e5e11578a0cb1bbb9b62
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.SqlServer.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..29047c285da6f08bb7cb85973e1f3a364e3c1c15
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.SqlServer.ttinclude
@@ -0,0 +1,144 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	{
+		GenerateProcedureDbType = p => p.DataType == "Structured" && p.SchemaType != null;
+
+		var afterGenerateLinqToDBModel = AfterGenerateLinqToDBModel;
+		AfterGenerateLinqToDBModel = () =>
+		{
+			afterGenerateLinqToDBModel();
+			DoGenerateSqlServerFreeText();
+		};
+
+		var buildColumnComparison = BuildColumnComparison;
+		BuildColumnComparison = (c, padding1, padding2, last) =>
+		{
+			if (c.BuildType() == "SqlHierarchyId")
+				return string.Format("\t(bool)(t.{0}{1} == {0}{3}){2}", c.MemberName, padding1, last ? ");" : " &&", last ? "" : padding2);
+			else
+				return buildColumnComparison(c, padding1, padding2, last);
+		};
+	}
+#>
+<#+
+bool GenerateSqlServerFreeText = true; // Defines whether to generate extensions for Free Text search, or not
+
+void DoGenerateSqlServerFreeText()
+{
+	if (!GenerateSqlServerFreeText)
+		return;
+
+	Model.Usings.Add("System.Collections.Generic");
+	Model.Usings.Add("System.Linq.Expressions");
+	Model.Usings.Add("System.Reflection");
+	Model.Usings.Add("LinqToDB");
+	Model.Usings.Add("LinqToDB.DataProvider.SqlServer");
+	Model.Usings.Add("LinqToDB.Extensions");
+
+	DataContextObject.Members.Add(
+		new MemberGroup
+		{
+			Region  = "FreeTextTable",
+			Members =
+			{
+				new Class("FreeTextKey",
+					new MemberGroup
+					{
+						IsCompact = true,
+						Members   =
+						{
+							new Field(() => "T",   "Key"),
+							new Field(() => "int", "Rank")
+						}
+					})
+				{
+					GenericArguments = { "T" },
+					IsPartial        = false
+				},
+
+				new Field(() => "MethodInfo", "_freeTextTableMethod1")
+				{
+					AccessModifier = AccessModifier.Private,
+					IsStatic       = true,
+					InitValue      = "typeof(" + DataContextObject.Name + ").GetMethod(\"FreeTextTable\", new Type[] { typeof(string), typeof(string) })"
+				},
+
+				new Method(() => "ITable<FreeTextKey<TKey>>", "FreeTextTable",
+					new Func<string>[] { () => "string field", () => "string text" },
+					() => new[]
+					{
+						"return this.GetTable<FreeTextKey<TKey>>(",
+						"	this,",
+						"	_freeTextTableMethod1,",
+						"	field,",
+						"	text);",
+					})
+				{
+					GenericArguments = new List<string>() { "TTable", "TKey" },
+					Attributes = { new Attribute("FreeTextTableExpression") }
+				},
+
+				new Field(() => "MethodInfo", "_freeTextTableMethod2")
+				{
+					AccessModifier = AccessModifier.Private,
+					IsStatic       = true,
+					InitValue      =                                                                                                                                                      Environment.NewLine +
+					"	typeof(" + DataContextObject.Name + ").GetMethods()"                                                                                                            + Environment.NewLine +
+					"		.Where(m => m.Name == \"FreeTextTable\" &&  m.IsGenericMethod && m.GetParameters().Length == 2)"                                                            + Environment.NewLine +
+					"		.Where(m => m.GetParameters()[0].ParameterType.IsGenericTypeEx() && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))" + Environment.NewLine +
+					"		.Where(m => m.GetParameters()[1].ParameterType == typeof(string))"                                                                                          + Environment.NewLine +
+					"		.Single()"
+				},
+
+				new Method(() => "ITable<FreeTextKey<TKey>>", "FreeTextTable",
+					new Func<string>[] { () => "Expression<Func<TTable,string>> fieldSelector", () => "string text" },
+					() => new[]
+					{
+						"return this.GetTable<FreeTextKey<TKey>>(",
+						"	this,",
+						"	_freeTextTableMethod2,",
+						"	fieldSelector,",
+						"	text);",
+					})
+				{
+					GenericArguments = { "TTable", "TKey" },
+					Attributes       = { new Attribute("FreeTextTableExpression") }
+				},
+			}
+		}
+	);
+}
+
+LinqToDB.Data.DataConnection GetSqlServerConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.SqlServer.SqlServerTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetSqlServerConnection(string server, string database)
+{
+	return GetSqlServerConnection(string.Format("Data Source={0};Database={1};Integrated Security=SSPI", server, database));
+}
+
+LinqToDB.Data.DataConnection GetSqlServerConnection(string server, string database, string user, string password)
+{
+	return GetSqlServerConnection(string.Format("Server={0};Database={1};User Id={2};Password={3};", server, database, user, password));
+}
+
+void LoadSqlServerMetadata(string connectionString)
+{
+	using (var dataConnection = GetSqlServerConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadSqlServerMetadata(string server, string database)
+{
+	using (var dataConnection = GetSqlServerConnection(server, database))
+		LoadMetadata(dataConnection);
+}
+
+void LoadSqlServerMetadata(string server, string database, string user, string password)
+{
+	using (var dataConnection = GetSqlServerConnection(server, database, user, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Sybase.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Sybase.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..bced686ff81440076443ed6565daca09a06c2927
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Sybase.Tools.ttinclude
@@ -0,0 +1,2 @@
+<#@ include file="LinqToDB.Tools.ttinclude" #>
+<#@ include file="LinqToDB.Sybase.ttinclude" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Sybase.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Sybase.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..52c6e6726e689db5b1b5d930a3b9f9753dcc86b9
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Sybase.ttinclude
@@ -0,0 +1,79 @@
+<#@ include file="LinqToDB.ttinclude" #>
+<#
+	{
+		var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel;
+		BeforeGenerateLinqToDBModel = () =>
+		{
+			beforeGenerateLinqToDBModel();
+			GenerateSybaseTypes();
+		};
+	}
+#><#+
+bool GenerateSybaseSystemTables = false; // Defines whether to generate Sybase sysobjects tables or not
+
+void GenerateSybaseTypes()
+{
+	if (GenerateSybaseSystemTables)
+	{
+		Tables.Add("sysobjects", new Table
+		{
+			Name                    = "sysobjects",
+			TableName               = "sysobjects",
+			TypeName                = "SysObject",
+			DataContextPropertyName = "SysObjects",
+			BaseClass               = BaseEntityClass,
+			Columns                 = new Dictionary<string,Column>()
+			{
+				{ "name",      new Column { Name = "name",      ColumnName = "name",      ColumnType = "varchar",  TypeBuilder = () => "string",   DbType = DbType.AnsiString,  /*Length = 255*/             }},
+				{ "id",        new Column { Name = "id",        ColumnName = "id",        ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "uid",       new Column { Name = "uid",       ColumnName = "uid",       ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "type",      new Column { Name = "type",      ColumnName = "type",      ColumnType = "char",     TypeBuilder = () => "string",   DbType = DbType.AnsiStringFixedLength, /*Length = 2,*/    }},
+				{ "userstat",  new Column { Name = "userstat",  ColumnName = "userstat",  ColumnType = "smallint", TypeBuilder = () => "short",    DbType = DbType.Int16,                                    }},
+				{ "sysstat",   new Column { Name = "sysstat",   ColumnName = "sysstat",   ColumnType = "smallint", TypeBuilder = () => "short",    DbType = DbType.Int16,                                    }},
+				{ "indexdel",  new Column { Name = "indexdel",  ColumnName = "indexdel",  ColumnType = "smallint", TypeBuilder = () => "short",    DbType = DbType.Int16,                                    }},
+				{ "schemacnt", new Column { Name = "schemacnt", ColumnName = "schemacnt", ColumnType = "smallint", TypeBuilder = () => "short",    DbType = DbType.Int16,                                    }},
+				{ "sysstat2",  new Column { Name = "sysstat2",  ColumnName = "sysstat2",  ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "crdate",    new Column { Name = "crdate",    ColumnName = "crdate",    ColumnType = "datetime", TypeBuilder = () => "DateTime", DbType = DbType.DateTime                                  }},
+				{ "expdate",   new Column { Name = "expdate",   ColumnName = "expdate",   ColumnType = "datetime", TypeBuilder = () => "DateTime", DbType = DbType.DateTime                                  }},
+				{ "deltrig",   new Column { Name = "deltrig",   ColumnName = "deltrig",   ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "instrig",   new Column { Name = "instrig",   ColumnName = "instrig",   ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "updtrig",   new Column { Name = "updtrig",   ColumnName = "updtrig",   ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "seltrig",   new Column { Name = "seltrig",   ColumnName = "seltrig",   ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "ckfirst",   new Column { Name = "ckfirst",   ColumnName = "ckfirst",   ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "cache",     new Column { Name = "cache",     ColumnName = "cache",     ColumnType = "smallint", TypeBuilder = () => "short",    DbType = DbType.Int16                                     }},
+				{ "audflags",  new Column { Name = "audflags",  ColumnName = "audflags",  ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,  IsNullable = true                 }},
+				{ "objspare",  new Column { Name = "objspare",  ColumnName = "objspare",  ColumnType = "int",      TypeBuilder = () => "int",      DbType = DbType.Int32,                                    }},
+				{ "versionts", new Column { Name = "versionts", ColumnName = "versionts", ColumnType = "binary",   TypeBuilder = () => "byte[]",   DbType = DbType.Binary, IsNullable = true, /*Length = 6*/ }},
+				{ "loginame",  new Column { Name = "loginame",  ColumnName = "loginame",  ColumnType = "varchar",  TypeBuilder = () => "string",   DbType = DbType.AnsiString,  /*Length = 30*/              }},
+			}
+		});
+	}
+}
+
+LinqToDB.Data.DataConnection GetSybaseConnection(string connectionString)
+{
+	return LinqToDB.DataProvider.Sybase.SybaseTools.CreateDataConnection(connectionString);
+}
+
+LinqToDB.Data.DataConnection GetSybaseConnection(string server, string database)
+{
+	return GetSybaseConnection(string.Format("Data Source={0};Database={1};Integrated Security=SSPI", server, database));
+}
+
+LinqToDB.Data.DataConnection GetSybaseConnection(string server, string port, string database, string uid, string password)
+{
+	return GetSybaseConnection(string.Format("Data Source={0};Port={1};Database={2};Uid={3};Password={4};Charset=utf8;", server, port, database, uid, password));
+}
+
+void LoadSybaseMetadata(string connectionString)
+{
+	using (var dataConnection = GetSybaseConnection(connectionString))
+		LoadMetadata(dataConnection);
+}
+
+void LoadSybaseMetadata(string server, string port, string database, string uid, string password)
+{
+	using (var dataConnection = GetSybaseConnection(server, port, database, uid, password))
+		LoadMetadata(dataConnection);
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.Tools.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.Tools.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..d804bb85f737d248fb336c5a61e116e54d8dea57
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.Tools.ttinclude
@@ -0,0 +1 @@
+<#@ assembly name="$(LinqToDBT4ToolsDirectory)linq2db.dll" #>
diff --git a/src/Version/LinqToDB.Templates/LinqToDB.ttinclude b/src/Version/LinqToDB.Templates/LinqToDB.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..0aa897a12f42602a506ee540d14effb295099263
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/LinqToDB.ttinclude
@@ -0,0 +1,1044 @@
+<#@ assembly name="System.Data"        #>
+<#@ import namespace="System.Data"     #>
+<#@ import namespace="LinqToDB.Data"   #>
+<#@ import namespace="System.Text" #>
+<#@ include file="DataModel.ttinclude" #>
+<#
+	if (BaseDataContextClass == null)
+		BaseDataContextClass = "LinqToDB.Data.DataConnection";
+#>
+<#+
+Action BeforeGenerateLinqToDBModel = () => {};
+Action AfterGenerateLinqToDBModel  = () => {};
+
+Func<Table,MemberBase> GenerateProviderSpecificTable = t => null;
+Func<Parameter, bool>  GenerateProcedureDbType       = p => false;
+
+bool   GenerateObsoleteAttributeForAliases = false;
+bool   GenerateFindExtensions              = true;
+bool   IsCompactColumns                    = true;
+bool   IsCompactColumnAliases              = true;
+bool   GenerateDataTypes                   = false;
+bool?  GenerateLengthProperty              = null;
+bool?  GeneratePrecisionProperty           = null;
+bool?  GenerateScaleProperty               = null;
+bool   GenerateDbTypes                     = false;
+bool   GenerateSchemaAsType                = false;
+bool   GenerateViews                       = true;
+bool   GenerateProcedureResultAsList       = false;
+bool   PrefixTableMappingWithSchema        = true;
+string SchemaNameSuffix                    = "Schema";
+string SchemaDataContextTypeName           = "DataContext";
+
+Dictionary<string,string> SchemaNameMapping = new Dictionary<string,string>();
+
+Func<string,string,IEnumerable<Method>> GetConstructors =  (conf, name) => GetConstructorsImpl(conf, name);
+
+Func<Column, string, string, bool, string> BuildColumnComparison = (c, padding1, padding2, last) =>
+{
+	return string.Format("\tt.{0}{1} == {0}{3}{2}", c.MemberName, padding1, last ? ");" : " &&", last ? "" : padding2);
+};
+
+static IEnumerable<Method> GetConstructorsImpl(string defaultConfiguration, string name)
+{
+	if (defaultConfiguration == null)
+		yield return new Method((Func<string>)null, name);
+	else
+		yield return new Method((Func<string>)null, name) { AfterSignature = { ": base(" + ToStringLiteral(defaultConfiguration) + ")" } };
+	yield return new Method((Func<string>)null, name, new Func<string>[] { () => "string configuration" }) { AfterSignature = { ": base(configuration)" } };
+}
+
+void GenerateTypesFromMetadata()
+{
+	BeforeGenerateLinqToDBModel();
+
+	Model.Usings.Add("LinqToDB");
+	Model.Usings.Add("LinqToDB.Mapping");
+
+	if (NamespaceName == null)
+		NamespaceName = "DataModel";
+
+	string schemaName;
+
+	var schemas =
+	(
+		from t in Tables.Values
+		where GenerateSchemaAsType && t.Schema != null && !t.TableSchema.IsDefaultSchema
+		group t by t.Schema into gr
+		orderby gr.Key
+		let typeName = SchemaNameMapping.TryGetValue(gr.Key, out schemaName) ? schemaName : gr.Key
+		select new
+		{
+			Name            = gr.Key,
+			TypeName        = typeName + SchemaNameSuffix,
+			PropertyName    = typeName,
+			Props           = new MemberGroup { IsCompact = true },
+			Aliases         = new MemberGroup { IsCompact = true, Region = "Alias members" },
+			TableExtensions = new MemberGroup { Region = "Table Extensions" },
+			Type            = new Class(typeName + SchemaNameSuffix) { IsStatic = true },
+			Tables          = gr.ToList(),
+			DataContext     = new Class(SchemaDataContextTypeName),
+			Procedures      = new MemberGroup(),
+			Functions       = new MemberGroup(),
+			TableFunctions  = new MemberGroup { Region = "Table Functions" },
+		}
+	).ToDictionary(t => t.Name);
+
+	var procSchemas =
+	(
+		from p in Procedures.Values
+		where GenerateSchemaAsType && p.Schema != null && !p.IsDefaultSchema && !schemas.ContainsKey(p.Schema)
+		group p by p.Schema into gr
+		orderby gr.Key
+		let typeName = SchemaNameMapping.TryGetValue(gr.Key, out schemaName) ? schemaName : gr.Key
+		select new
+		{
+			Name            = gr.Key,
+			TypeName        = typeName + SchemaNameSuffix,
+			PropertyName    = typeName,
+			Props           = new MemberGroup { IsCompact = true },
+			Aliases         = new MemberGroup { IsCompact = true, Region = "Alias members" },
+			TableExtensions = new MemberGroup { Region = "Table Extensions" },
+			Type            = new Class(typeName + SchemaNameSuffix) { IsStatic = true },
+			Tables          = new List<Table>(),
+			DataContext     = new Class(SchemaDataContextTypeName),
+			Procedures      = new MemberGroup(),
+			Functions       = new MemberGroup(),
+			TableFunctions  = new MemberGroup { Region = "Table Functions" },
+		}
+	).ToDictionary(s => s.Name);
+
+	foreach(var schema in procSchemas)
+		schemas.Add(schema.Key, schema.Value);
+
+	var defProps           = new MemberGroup { IsCompact = true };
+	var defAliases         = new MemberGroup { IsCompact = true, Region = "Alias members" };
+	var defTableExtensions = new MemberGroup { };
+
+	if (schemas.Count > 0)
+	{
+		var body = new List<Func<IEnumerable<string>>>();
+
+		var schemaGroup   = new MemberGroup { Region = "Schemas" };
+		var schemaMembers = new MemberGroup { IsCompact = true   };
+
+		var maxLen1 = schemas.Values.Max(schema => schema.PropertyName.Trim().Length);
+		var maxLen2 = schemas.Values.Max(schema => schema.TypeName.    Trim().Length);
+
+		foreach (var schema in schemas.Values)
+		{
+			schemaMembers.Members.Add(new Property(() => schema.TypeName + "." + SchemaDataContextTypeName, schema.PropertyName));
+			body.Add(() => new string[] {
+				schema.PropertyName + LenDiff(maxLen1, schema.PropertyName) +
+				" = new " + schema.TypeName + "." + LenDiff(maxLen2, schema.TypeName) +
+				SchemaDataContextTypeName + "(this);"});
+		}
+
+		schemaGroup.Members.Add(schemaMembers);
+		schemaGroup.Members.Add(new Method(() => "void", "InitSchemas", new Func<string>[0], body.ToArray()));
+
+		DataContextObject.Members.Add(schemaGroup);
+	}
+
+	if (GenerateConstructors)
+	{
+		foreach (var c in GetConstructors(DefaultConfiguration, DataContextObject.Name))
+		{
+			if (c.BodyBuilders.Count > 0)
+				c.BodyBuilders.Add(() => new[] { "" });
+
+			if (schemas.Count > 0)
+				c.BodyBuilders.Add(() => new[] { "InitSchemas();" });
+
+			c.BodyBuilders.Add(() => new [] {"InitDataContext();", "InitMappingSchema();" });
+
+			DataContextObject.Members.Add(c);
+		}
+	}
+
+	DataContextObject.Members.Add(new MemberGroup
+	{
+		IsCompact = true,
+		Members   =
+		{
+			new Method(() => "void", "InitDataContext"  ) { AccessModifier = AccessModifier.Partial },
+			new Method(() => "void", "InitMappingSchema") { AccessModifier = AccessModifier.Partial }
+		}
+	});
+
+	if (Tables.Count > 0)
+		DataContextObject.Members.Insert(0, defProps);
+
+	foreach (var schema in schemas.Values)
+	{
+		schema.Type.Members.Add(schema.DataContext);
+		schema.DataContext.Members.Insert(0, schema.Props);
+
+		schema.DataContext.Members.Add(new Field (() => "IDataContext", "_dataContext") { AccessModifier = AccessModifier.Private, IsReadonly = true });
+		schema.DataContext.Members.Add(new Method(() => null, schema.DataContext.Name, new Func<string>[] { () => "IDataContext dataContext" }, () => new[] { "_dataContext = dataContext;" }));
+
+		foreach (var t in schema.Tables)
+		{
+			t.TypePrefix = schema.TypeName + ".";
+		}
+	}
+
+	var associationExtensions = new MemberGroup() {Region = "Associations"};
+
+	foreach (var t in Tables.Values.OrderBy(tbl => tbl.IsProviderSpecific).ThenBy(tbl => tbl.TypeName))
+	{
+		Action<Class> addType     = tp => Model.Types.Add(tp);
+		var props                 = defProps;
+		var aliases               = defAliases;
+		var tableExtensions       = defTableExtensions;
+
+		if (t.IsView && !GenerateViews) {
+			continue;
+		}
+
+		var schema = t.Schema != null && schemas.ContainsKey(t.Schema) ? schemas[t.Schema] : null;
+
+		if (schema != null)
+		{
+			var si = schemas[t.Schema];
+
+			addType         = tp => si.Type.Members.Add(tp);
+			props           = si.Props;
+			aliases         = si.Aliases;
+			tableExtensions = si.TableExtensions;
+		}
+
+		MemberBase dcProp = t.IsProviderSpecific ?
+			GenerateProviderSpecificTable(t) :
+			new Property(
+				() => string.Format("ITable<{0}>", t.TypeName),
+				t.DataContextPropertyName,
+				() => new[] { string.Format((schema == null ? "this" : "_dataContext") + ".GetTable<{0}>()", t.TypeName) },
+				null);
+
+		if (dcProp == null) continue;
+
+		t.DataContextProperty = dcProp;
+
+		props.Members.Add(dcProp);
+
+		Property aProp = null;
+
+		if (t.AliasPropertyName != null && t.AliasPropertyName != t.DataContextPropertyName)
+		{
+			aProp = new Property(
+				() => string.Format("ITable<{0}>", t.TypeName),
+				t.AliasPropertyName,
+				() => new[] { t.DataContextPropertyName },
+				null);
+
+			if (GenerateObsoleteAttributeForAliases)
+				aProp.Attributes.Add(new Attribute("Obsolete", ToStringLiteral("Use " + t.DataContextPropertyName + " instead.")));
+
+			aliases.Members.Add(aProp);
+		}
+
+		var tableAttrs = new List<string>();
+
+		if (DatabaseName != null) tableAttrs.Add("Database="  + ToStringLiteral(DatabaseName));
+		if (t.Schema     != null) tableAttrs.Add("Schema="    + ToStringLiteral(t.Schema));
+
+		tableAttrs.Add((tableAttrs.Count == 0 ? "" : "Name=") + ToStringLiteral(t.TableName));
+
+		if (t.IsView)
+			tableAttrs.Add("IsView=true");
+
+		t.Attributes.Add(new Attribute("Table", tableAttrs.ToArray()) { IsSeparated = true } );
+
+		var comments = new List<string>();
+
+		if (!string.IsNullOrWhiteSpace(t.Description))
+		{
+			comments.Add("/ <summary>");
+			foreach (var line in t.Description.Split('\n'))
+				comments.Add("/ " + line.TrimEnd());
+			comments.Add("/ </summary>");
+		}
+
+		if (comments.Count > 0)
+		{
+			t.     Comment.AddRange(comments);
+			dcProp.Comment.AddRange(comments);
+
+			if (aProp != null)
+				aProp.Comment.AddRange(comments);
+		}
+
+		var columns        = new MemberGroup { IsCompact = IsCompactColumns };
+		var columnAliases  = new MemberGroup { IsCompact = IsCompactColumnAliases, Region = "Alias members" };
+		var nPKs           = t.Columns.Values.Count(c => c.IsPrimaryKey);
+		var allNullable    = t.Columns.Values.All  (c => c.IsNullable || c.IsIdentity);
+		var nameMaxLen     = t.Columns.Values.Max  (c => (int?)(c.MemberName == c.ColumnName
+			? 0
+			: ToStringLiteral(c.ColumnName).Length)) ?? 0;
+		var dbTypeMaxLen   = t.Columns.Values.Max  (c => (int?)(c.ColumnType.Length)) ?? 0;
+		var dataTypeMaxLen = t.Columns.Values.Where(c => c.DataType != null).Max  (c => (int?)(c.DataType.Length)) ?? 0;
+		var dataTypePrefix = t.Columns.Values.Any  (c => c.MemberName == "DataType") ? "LinqToDB." : "";
+
+		foreach (var c in t.Columns.Values)
+		{
+			// Column.
+			//
+			var ca = new Attribute("Column");
+			var canBeReplaced = true;
+
+			if (c.MemberName != c.ColumnName)
+			{
+				var columnNameInAttr = ToStringLiteral(c.ColumnName);
+
+				var space = new string(' ', nameMaxLen - columnNameInAttr.Length);
+
+				ca.Parameters.Add(columnNameInAttr + space);
+				canBeReplaced = false;
+			}
+			else if (nameMaxLen > 0)
+			{
+				ca.Parameters.Add(new string(' ', nameMaxLen));
+				canBeReplaced = false;
+			}
+
+			if (GenerateDbTypes)
+			{
+				var space = new string(' ', dbTypeMaxLen - c.ColumnType.Length);
+
+				ca.Parameters.Add("DbType=" + ToStringLiteral(c.ColumnType) + space);
+				canBeReplaced = false;
+			}
+
+			if (GenerateDataTypes)
+			{
+				var space = new string(' ', dataTypeMaxLen - c.DataType.Length);
+				ca.Parameters.Add("DataType=" + dataTypePrefix + c.DataType + space);
+				canBeReplaced = false;
+			}
+
+			if (GenerateDataTypes && !GenerateLengthProperty.HasValue || GenerateLengthProperty == true)
+			{
+				if (c.Length    != null) ca.Parameters.Add("Length="    + (c.Length == int.MaxValue ? "int.MaxValue" : c.Length.ToString()));
+				canBeReplaced = false;
+			}
+
+			if (GenerateDataTypes && !GeneratePrecisionProperty.HasValue || GeneratePrecisionProperty == true)
+			{
+				if (c.Precision != null) ca.Parameters.Add("Precision=" + c.Precision);
+				canBeReplaced = false;
+			}
+
+			if (GenerateDataTypes && !GenerateScaleProperty.HasValue || GenerateScaleProperty == true)
+			{
+				if (c.Scale     != null) ca.Parameters.Add("Scale=" + c.Scale);
+				canBeReplaced = false;
+			}
+
+			if (c.SkipOnInsert && !c.IsIdentity)
+			{
+				ca.Parameters.Add("SkipOnInsert=true");
+				canBeReplaced = false;
+			}
+
+			if (c.SkipOnUpdate && !c.IsIdentity)
+			{
+				ca.Parameters.Add("SkipOnUpdate=true");
+				canBeReplaced = false;
+			}
+
+			if (c.IsDiscriminator)
+			{
+				ca.Parameters.Add("IsDiscriminator=true");
+				canBeReplaced = false;
+			}
+
+			c.Attributes.Add(ca);
+
+			// PK.
+			//
+			if (c.IsPrimaryKey)
+			{
+				var pka = new Attribute("PrimaryKey");
+
+				if (nPKs > 1)
+					pka.Parameters.Add(c.PrimaryKeyOrder.ToString());
+
+				if (canBeReplaced)
+					c.Attributes[0] = pka;
+				else
+					c.Attributes.Add(pka);
+
+				canBeReplaced = false;
+			}
+
+			// Identity.
+			//
+			if (c.IsIdentity)
+			{
+				var ida = new Attribute("Identity");
+
+				if (canBeReplaced)
+					c.Attributes[0] = ida;
+				else
+					c.Attributes.Add(ida);
+
+				canBeReplaced = false;
+			}
+
+			// Nullable.
+			//
+			if (c.IsNullable)
+				c.Attributes.Add(new Attribute((allNullable ? "" : "   ") + "Nullable"));
+			else if (!c.IsIdentity)
+				c.Attributes.Add(new Attribute("NotNull"));
+
+			var columnComments = new List<string>();
+
+			if (!string.IsNullOrWhiteSpace(c.Description))
+			{
+				columnComments.Add("/ <summary>");
+				foreach (var line in c.Description.Split('\n'))
+					columnComments.Add("/ " + line.TrimEnd());
+				columnComments.Add("/ </summary>");
+			}
+
+			if (columnComments.Count > 0)
+				c.Comment.AddRange(columnComments);
+
+			// End line comment.
+			//
+			c.EndLineComment = c.ColumnType;
+
+			SetPropertyValue(c, "IsNotifying", true);
+			SetPropertyValue(c, "IsEditable",  true);
+
+			columns.Members.Add(c);
+
+			// Alias.
+			//
+			if (c.AliasName != null && c.AliasName != c.MemberName)
+			{
+				var caProp = new Property(
+					c.TypeBuilder,
+					c.AliasName,
+					() => new[] { c.MemberName },
+					() => new[] { c.MemberName + " = value;"});
+
+				caProp.Comment.AddRange(columnComments);
+
+				if (GenerateObsoleteAttributeForAliases)
+					caProp.Attributes.Add(new Attribute("Obsolete", ToStringLiteral("Use " + c.MemberName + " instead.")));
+
+				caProp.Attributes.Add(new Attribute("ColumnAlias" , ToStringLiteral(c.MemberName)));
+
+				columnAliases.Members.Add(caProp);
+			}
+		}
+
+		t.Members.Add(columns);
+
+		if (columnAliases.Members.Count > 0)
+			t.Members.Add(columnAliases);
+
+		if (GenerateAssociations || GenerateAssociationExtensions)
+		{
+			var keys = t.ForeignKeys.Values.ToList();
+
+			if (!GenerateBackReferences)
+				keys = keys.Where(k => k.BackReference != null).ToList();
+
+			if (keys.Count > 0)
+			{
+				var associations          = new MemberGroup { Region = "Associations" };
+				var extensionAssociations = new MemberGroup { Region = t.Name + " Associations"};
+
+				foreach (var key in keys.OrderBy(k => k.MemberName))
+				{
+					key.Comment.Add("/ <summary>");
+					key.Comment.Add("/ " + key.KeyName);
+					key.Comment.Add("/ </summary>");
+
+					if (key.AssociationType == AssociationType.OneToMany)
+						key.TypeBuilder = () => string.Format(OneToManyAssociationType, key.OtherTable.TypePrefix + key.OtherTable.TypeName);
+					else
+						key.TypeBuilder = () => key.OtherTable.TypePrefix + key.OtherTable.TypeName;
+
+					var aa = new Attribute("Association");
+
+					aa.Parameters.Add("ThisKey="   + ToStringLiteral(string.Join(", ", (from c in key.ThisColumns  select c.MemberName).ToArray())));
+					aa.Parameters.Add("OtherKey="  + ToStringLiteral(string.Join(", ", (from c in key.OtherColumns select c.MemberName).ToArray())));
+					aa.Parameters.Add("CanBeNull=" + (key.CanBeNull ? "true" : "false"));
+
+					switch (key.AssociationType)
+					{
+						case AssociationType.OneToOne  : aa.Parameters.Add("Relationship=Relationship.OneToOne");  break;
+						case AssociationType.OneToMany : aa.Parameters.Add("Relationship=Relationship.OneToMany"); break;
+						case AssociationType.ManyToOne : aa.Parameters.Add("Relationship=Relationship.ManyToOne"); break;
+					}
+
+					if (key.BackReference != null)
+					{
+						if (!string.IsNullOrEmpty(key.KeyName))
+							aa.Parameters.Add("KeyName=" + ToStringLiteral(key.KeyName));
+						if (GenerateBackReferences && !string.IsNullOrEmpty(key.BackReference.MemberName))
+							aa.Parameters.Add("BackReferenceName=" + ToStringLiteral(key.BackReference.MemberName));
+					}
+					else
+					{
+						aa.Parameters.Add("IsBackReference=true");
+					}
+
+					key.Attributes.Add(aa);
+
+					SetPropertyValue(key, "IsNotifying", true);
+					SetPropertyValue(key, "IsEditable",  true);
+
+					associations.Members.Add(key);
+
+					var extension = new Method(() => string.Format("IQueryable<{0}>", key.OtherTable.TypePrefix + key.OtherTable.TypeName), GetAssociationExtensionPluralName(key));
+					extension.Name = GetAssociationExtensionPluralName(key);
+
+					extension.ParameterBuilders.Add(() => string.Format("this {0}{1} obj", t.TypePrefix, t.TypeName));
+
+					extension.ParameterBuilders.Add(() => "IDataContext db");
+					extension.Attributes.Add(aa);
+					extension.IsStatic = true;
+
+					extension.Comment.Add("/ <summary>");
+					extension.Comment.Add("/ " + key.KeyName);
+					extension.Comment.Add("/ </summary>");
+
+					Func<string> builder = () =>
+					{
+						var sb = new StringBuilder();
+						sb
+							.Append("return db.GetTable<")
+							.Append(key.OtherTable.TypePrefix + key.OtherTable.TypeName)
+							.Append(">().Where(c => ");
+						for (var i = 0; i < key.OtherColumns.Count; i++)
+						{
+							sb.Append("c.")
+								.Append(key.OtherColumns[i].MemberName)
+								.Append(" == obj.")
+								.Append(key.ThisColumns[i].MemberName)
+								.Append(" && ");
+						}
+						sb.Length -= 4;
+						sb.Append(");");
+
+						return sb.ToString();
+					};
+
+					extension.BodyBuilders.Add(() => new[] { builder() });
+
+					extensionAssociations.Members.Add(extension);
+
+					if (key.AssociationType != AssociationType.OneToMany)
+					{
+						var single = new Method(() => t.TypePrefix + t.TypeName, GetAssociationExtensionSinglularName(key));
+						
+						single.ParameterBuilders.Add(() => string.Format("this {0}{1} obj", key.OtherTable.TypePrefix, key.OtherTable.TypeName));
+
+						single.ParameterBuilders.Add(() => "IDataContext db");
+						single.Attributes.Add(aa);
+						single.IsStatic = true;
+
+						single.Comment.Add("/ <summary>");
+						single.Comment.Add("/ " + key.KeyName);
+						single.Comment.Add("/ </summary>");
+
+						Func<string> builderSingle = () =>
+						{
+							var sb = new StringBuilder();
+							sb
+								.Append("return db.GetTable<")
+								.Append(t.TypePrefix + t.TypeName)
+								.Append(">().Where(c => ");
+							for (var i = 0; i < key.OtherColumns.Count; i++)
+							{
+								sb.Append("c.")
+									.Append(key.ThisColumns[i].MemberName)
+									.Append(" == obj.")
+									.Append(key.OtherColumns[i].MemberName)
+									.Append(" && ");
+							}
+							sb.Length -= 4;
+							sb.Append(");");
+
+							return sb.ToString();
+						};
+
+						single.BodyBuilders.Add(() =>
+						{
+							var sb = new StringBuilder(builderSingle());
+							sb.Length -= 1;
+
+							if (key.CanBeNull)
+								sb.Append(".FirstOrDefault();");
+							else
+								sb.Append(".First();");
+
+							return new [] { sb.ToString() };
+						});
+
+						extensionAssociations.Members.Add(single);
+					}
+				}
+
+				if (GenerateAssociations)
+					t.Members.Add(associations);
+				if (GenerateAssociationExtensions)
+					associationExtensions.Members.Add(extensionAssociations);
+			}
+		}
+
+		if (GenerateFindExtensions && nPKs > 0)
+		{
+			var PKs         = t.Columns.Values.Where(c => c.IsPrimaryKey).ToList();
+			var maxNameLen1 = PKs.Max(c => (int?)c.MemberName.Length) ?? 0;
+			var maxNameLen2 = PKs.Take(nPKs - 1).Max(c => (int?)c.MemberName.Length) ?? 0;
+
+			tableExtensions.Members.Add(
+				new Method(
+					() => t.TypeName,
+					"Find",
+					new Func<string>[] { () => (string.Format("this ITable<{0}> table", t.TypeName)) }
+						.Union(PKs.Select(c => (Func<string>)(() => c.BuildType() + " " + c.MemberName))),
+					() => new[] { "return table.FirstOrDefault(t =>" }
+						.Union(PKs.SelectMany((c,i) =>
+						{
+							var ss = new List<string>();
+
+							if (c.Conditional != null)
+								ss.Add("#if " + c.Conditional);
+
+							ss.Add(BuildColumnComparison(c, LenDiff(maxNameLen1, c.MemberName), LenDiff(maxNameLen2, c.MemberName), i == nPKs - 1));
+
+							if (c.Conditional != null)
+							{
+								if (ss[1].EndsWith(");"))
+								{
+									ss[1] = ss[1].Substring(0, ss[1].Length - 2);
+									ss.Add("#endif");
+									ss.Add("\t\t);");
+								}
+								else
+								{
+									ss.Add("#endif");
+								}
+							}
+
+							return ss;
+						})))
+				{
+					IsStatic = true
+				});
+		}
+
+		addType(t);
+
+		if (!string.IsNullOrWhiteSpace(t.AliasTypeName))
+		{
+			var aClass = new Class(t.AliasTypeName)
+			{
+				BaseClass = t.TypeName
+			};
+
+			if (comments.Count > 0)
+				aClass.Comment.AddRange(comments);
+
+			if (GenerateObsoleteAttributeForAliases)
+				aClass.Attributes.Add(new Attribute("Obsolete", ToStringLiteral("Use " + t.TypeName + " instead.")));
+
+			Model.Types.Add(aClass);
+		}
+	}
+
+	if (associationExtensions.Members.Count > 0)
+		defTableExtensions.Members.Add(associationExtensions);
+
+	if (defAliases.Members.Count > 0)
+		DataContextObject.Members.Add(defAliases);
+
+	foreach (var schema in schemas.Values)
+		if (schema.Aliases.Members.Count > 0)
+			schema.Type.Members.Add(defAliases);
+
+	if (Procedures.Count > 0)
+	{
+		Model.Usings.Add("System.Collections.Generic");
+		Model.Usings.Add("System.Data");
+		Model.Usings.Add("LinqToDB.Data");
+		Model.Usings.Add("LinqToDB.Common");
+
+		if (Procedures.Values.Any(p => p.IsTableFunction))
+			Model.Usings.Add("System.Reflection");
+
+		if (Procedures.Values.Any(p => p.IsAggregateFunction))
+			Model.Usings.Add("System.Linq.Expressions");
+
+		var procs = new MemberGroup();
+		var funcs = new MemberGroup();
+		var tabfs = new MemberGroup { Region = "Table Functions" };
+
+		foreach (var p in Procedures.Values.Where(
+			proc => proc.IsLoaded || proc.IsFunction && !proc.IsTableFunction ||
+			proc.IsTableFunction && proc.ResultException != null
+			))
+		{
+			Action<MemberGroup> addProcs = tp => procs.Members.Add(tp);
+			Action<MemberGroup> addFuncs = tp => funcs.Members.Add(tp);
+			Action<MemberGroup> addTabfs = tp => tabfs.Members.Add(tp);
+
+			var thisDataContext = "this";
+
+			var schema = p.Schema != null && schemas.ContainsKey(p.Schema) ? schemas[p.Schema] : null;
+
+			if (schema != null)
+			{
+				var si = schemas[p.Schema];
+
+				addProcs        = tp => si.Procedures.    Members.Add(tp);
+				addFuncs        = tp => si.Functions.     Members.Add(tp);
+				addTabfs        = tp => si.TableFunctions.Members.Add(tp);
+				thisDataContext = "_dataContext";
+			}
+
+			var proc = new MemberGroup { Region = p.Name };
+
+			if (!p.IsFunction)          addProcs(proc);
+			else if (p.IsTableFunction) addTabfs(proc);
+			else                        addFuncs(proc);
+
+			if (p.ResultException != null)
+			{
+				proc.Errors.Add(p.ResultException.Message);
+				continue;
+			}
+
+			proc.Members.Add(p);
+
+			if (p.IsTableFunction)
+			{
+				var tableAttrs = new List<string>();
+
+				if (DatabaseName != null) tableAttrs.Add("Database=" + ToStringLiteral(DatabaseName));
+				if (p.Schema     != null) tableAttrs.Add("Schema="   + ToStringLiteral(p.Schema));
+
+				tableAttrs.Add("Name=" + ToStringLiteral(p.ProcedureName));
+
+				p.Attributes.Add(new Attribute("Sql.TableFunction", tableAttrs.ToArray()));
+
+				p.TypeBuilder = () => "ITable<" + p.ResultTable.TypeName + ">";
+			}
+			else if (p.IsAggregateFunction)
+			{
+				p.IsStatic = true;
+				p.TypeBuilder = () => p.ProcParameters.Single(pr => pr.IsResult).ParameterType;
+				var paramCount = p.ProcParameters.Count(pr => !pr.IsResult);
+				p.Attributes.Add(new Attribute("Sql.Function", "Name=" + ToStringLiteral((p.Schema != null ? p.Schema + "." : null) + p.ProcedureName), "ServerSideOnly=true, IsAggregate = true" + (paramCount > 0 ? (", ArgIndices = new[] { " + string.Join(", ", Enumerable.Range(0, p.ProcParameters.Count(pr => !pr.IsResult))) + " }") : null)));
+
+				if (p.IsDefaultSchema || !GenerateSchemaAsType)
+					p.ParameterBuilders.Add(() => "this IEnumerable<TSource> src");
+				else // otherwise function will be generated in nested class, which doesn't support extension methods
+					p.ParameterBuilders.Add(() => "IEnumerable<TSource> src");
+
+				foreach (var inp in p.ProcParameters.Where(pr => !pr.IsResult))
+					p.ParameterBuilders.Add(() => $"Expression<Func<TSource, {inp.ParameterType}>> " + inp.ParameterName);
+
+				p.Name += "<TSource>";
+			}
+			else if (p.IsFunction)
+			{
+				p.IsStatic    = true;
+				p.TypeBuilder = () => p.ProcParameters.Single(pr => pr.IsResult).ParameterType;
+				p.Attributes.Add(new Attribute("Sql.Function", "Name=" + ToStringLiteral((p.Schema != null ? p.Schema + "." : null)  + p.ProcedureName), "ServerSideOnly=true"));
+			}
+			else
+			{
+				p.IsStatic    = true;
+				p.TypeBuilder = () => p.ResultTable == null
+					? "int"
+					: GenerateProcedureResultAsList
+						? "List<" + p.ResultTable.TypeName + ">"
+						: "IEnumerable<" + p.ResultTable.TypeName + ">";
+
+				if (p.IsDefaultSchema || !GenerateSchemaAsType)
+					p.ParameterBuilders.Add(() => "this DataConnection dataConnection");
+				else
+					p.ParameterBuilders.Add(() => "DataConnection dataConnection");
+			}
+
+			if (!p.IsAggregateFunction)
+				foreach (var pr in p.ProcParameters.Where(par => !par.IsResult))
+					p.ParameterBuilders.Add(() => string.Format("{0}{1} {2}",
+						pr.IsOut ? pr.IsIn ? "ref " : "out " : "", pr.ParameterType, pr.ParameterName));
+
+			if (p.IsTableFunction)
+			{
+				p.BodyBuilders.Add(() => new[]
+				{
+					string.Format("return " + thisDataContext + ".GetTable<{0}>(this, (MethodInfo)MethodBase.GetCurrentMethod()", p.ResultTable.TypeName)
+					+ (p.ProcParameters.Count == 0 ? ");" : ",")
+				});
+
+				for (var idx = 0; idx < p.ProcParameters.Count; idx++)
+				{
+					var i = idx;
+					p.BodyBuilders.Add(() => new []{ "\t" + p.ProcParameters[i].ParameterName + (i + 1 == p.ProcParameters.Count ? ");" : ",") });
+				}
+			}
+			else if (p.IsFunction)
+			{
+				p.BodyBuilders.Add(() => new [] { "throw new InvalidOperationException();" });
+			}
+			else
+			{
+				var spName =
+					SqlBuilder.BuildTableName(
+						new System.Text.StringBuilder(),
+						(string)SqlBuilder.Convert(DatabaseName,    LinqToDB.SqlProvider.ConvertType.NameToDatabase),
+						(string)SqlBuilder.Convert(p.Schema,        LinqToDB.SqlProvider.ConvertType.NameToSchema),
+						(string)SqlBuilder.Convert(p.ProcedureName, LinqToDB.SqlProvider.ConvertType.NameToQueryTable)
+					).ToString();
+
+				spName = ToStringLiteral(spName);
+
+				var inputParameters      = p.ProcParameters.Where(pp => pp.IsIn).            ToList();
+				var outputParameters     = p.ProcParameters.Where(pp => pp.IsOut).           ToList();
+				var inOrOutputParameters = p.ProcParameters.Where(pp => pp.IsIn || pp.IsOut).ToList();
+
+				spName += inOrOutputParameters.Count == 0
+					? (p.ResultTable == null || !GenerateProcedureResultAsList ? ");" : ").ToList();")
+					: ",";
+
+				var retName = "ret";
+				var retNo   = 0;
+
+				while (p.ProcParameters.Any(pp => pp.ParameterName == retName))
+					retName = "ret" + ++retNo;
+
+				var hasOut = outputParameters.Any(pr => pr.IsOut);
+				var prefix = hasOut ? "var " + retName + " = " : "return ";
+
+				if (p.ResultTable == null)
+					p.BodyBuilders.Add(() => new [] { prefix + "dataConnection.ExecuteProc(" + spName });
+				else
+				{
+					if (p.ResultTable.Columns.Values.Any(c => c.IsDuplicateOrEmpty))
+					{
+						p.BodyBuilders.Add(() => new []
+						{
+							"var ms = dataConnection.MappingSchema;",
+							"",
+							prefix + "dataConnection.QueryProc(dataReader =>",
+							"\tnew " + p.ResultTable.TypeName,
+							"\t{"
+						});
+
+						var n          = 0;
+						var maxNameLen = p.ResultTable.Columns.Values.Max(c => (int?)c.MemberName .Length) ?? 0;
+						var maxTypeLen = p.ResultTable.Columns.Values.Max(c => (int?)c.BuildType().Length) ?? 0;
+
+						foreach (var c in p.ResultTable.Columns.Values)
+						{
+							p.BodyBuilders.Add(() => new [] {string.Format("\t\t{0}{1} = Converter.ChangeTypeTo<{2}>{3}(dataReader.GetValue({4}), ms),",
+								c.MemberName, LenDiff(maxNameLen, c.MemberName), c.BuildType(), LenDiff(maxTypeLen, c.BuildType()), n++) });
+						}
+
+						p.BodyBuilders.Add(() => new [] {"\t},", "\t" + spName });
+					}
+					else
+					{
+						p.BodyBuilders.Add(() => new [] { prefix + "dataConnection.QueryProc<" + p.ResultTable.TypeName + ">(" + spName });
+					}
+				}
+
+				var maxLenSchema = inputParameters.Max(pr => (int?)pr.SchemaName.   Length) ?? 0;
+				var maxLenParam  = inputParameters.Max(pr => (int?)pr.ParameterName.Length) ?? 0;
+				var maxLenType   = inputParameters.Max(pr => (int?)("DataType." + pr.DataType).Length) ?? 0;
+
+				for (var idx = 0; idx < inOrOutputParameters.Count; idx++)
+				{
+					var i = idx;
+					var pr = inOrOutputParameters[i];
+
+					p.BodyBuilders.Add(() =>
+					{
+						var str = string.Format(
+							!pr.IsIn && pr.IsOut
+								? "\tnew DataParameter({0}, null, {3}{4})"
+								: "\tnew DataParameter({0}, {1}{2}, {3}{4})" + (GenerateProcedureDbType(pr) ? "{{ DbType = {5} }}" : null),
+							ToStringLiteral(pr.SchemaName),
+							LenDiff(maxLenSchema, pr.SchemaName),
+							pr.ParameterName,
+							LenDiff(maxLenParam, pr.ParameterName),
+							"DataType." + pr.DataType,
+							ToStringLiteral(pr.SchemaType));
+
+						if (pr.IsOut)
+						{
+							str += LenDiff(maxLenType, "DataType." + pr.DataType);
+							str += " { Direction = " + (pr.IsIn ? "ParameterDirection.InputOutput" : "ParameterDirection.Output");
+
+							if (pr.Size != null && pr.Size.Value != 0)
+								str += ", Size = " + pr.Size.Value;
+
+							str += " }";
+						}
+
+						// we need to call ToList(), because otherwise output parameters will not be updated
+						// with values. See https://msdn.microsoft.com/en-us/library/ms971497#gazoutas_topic6
+						str += i + 1 == inOrOutputParameters.Count
+							? ((GenerateProcedureResultAsList || outputParameters.Count > 0) && p.ResultTable != null ? ").ToList();" : ");")
+							: ",";
+
+						return new [] { str };
+					});
+				}
+
+				if (hasOut)
+				{
+					maxLenSchema = outputParameters.Max(pr => (int?)pr.SchemaName.   Length) ?? 0;
+					maxLenParam  = outputParameters.Max(pr => (int?)pr.ParameterName.Length) ?? 0;
+					maxLenType   = outputParameters.Max(pr => (int?)pr.ParameterType.Length) ?? 0;
+
+					p.BodyBuilders.Add(() => new [] { string.Empty });
+
+					foreach (var pr in p.ProcParameters.Where(_ => _.IsOut))
+					{
+						p.BodyBuilders.Add(() => new [] { string.Format("{0} {1}= Converter.ChangeTypeTo<{2}>{3}(((IDbDataParameter)dataConnection.Command.Parameters[{4}]).{5}Value);",
+							pr.ParameterName,
+							LenDiff(maxLenParam,  pr.ParameterName),
+							pr.ParameterType,
+							LenDiff(maxLenType,   pr.ParameterType),
+							ToStringLiteral(pr.SchemaName),
+							LenDiff(maxLenSchema, pr.SchemaName)) });
+					}
+
+					p.BodyBuilders.Add(() => new [] {"", "return " + retName + ";" });
+				}
+			}
+
+			if (p.ResultTable != null && p.ResultTable.DataContextPropertyName == null)
+			{
+				var columns = new MemberGroup { IsCompact = true };
+
+				foreach (var c in p.ResultTable.Columns.Values)
+				{
+					if (c.MemberName != c.ColumnName)
+						c.Attributes.Add(new Attribute("Column") { Parameters = { ToStringLiteral(c.ColumnName) } });
+					columns.Members.Add(c);
+				}
+
+				p.ResultTable.Members.Add(columns);
+				proc.Members.Add(p.ResultTable);
+			}
+		}
+
+		if (procs.Members.Count > 0)
+			Model.Types.Add(new Class(DataContextObject.Name + "StoredProcedures", procs) { IsStatic = true });
+
+		if (funcs.Members.Count > 0)
+			Model.Types.Add(new Class("SqlFunctions", funcs) { IsStatic = true });
+
+		if (tabfs.Members.Count > 0)
+			DataContextObject.Members.Add(tabfs);
+
+		MakeTypeMembersNamesUnique(DataContextObject, "InitDataContext", "InitMappingSchema");
+		MakeMembersNamesUnique(Model.Types, "Table");
+		foreach (var type in Model.Types.OfType<Class>())
+			MakeTypeMembersNamesUnique(type, exceptMethods: new [] { "Find", "InitDataContext", "InitMappingSchema" });
+
+		foreach (var schema in schemas.Values)
+		{
+			if (schema.Procedures.Members.Count > 0)
+				schema.Type.Members.Add(new Class(DataContextObject.Name + "StoredProcedures", schema.Procedures) { IsStatic = true });
+
+			if (schema.Functions.Members.Count > 0)
+				schema.Type.Members.Add(new Class("SqlFunctions", schema.Functions) { IsStatic = true });
+
+			if (schema.TableFunctions.Members.Count > 0)
+				schema.DataContext.Members.Add(schema.TableFunctions);
+
+			MakeTypeMembersNamesUnique(schema.DataContext, "InitDataContext", "InitMappingSchema");
+			foreach (var type in schema.Type.Members.OfType<Class>())
+				MakeTypeMembersNamesUnique(type);
+		}
+	}
+
+	if (defTableExtensions.Members.Count > 0)
+	{
+		Model.Usings.Add("System.Linq");
+		var tableExtensions = new Class("TableExtensions", defTableExtensions) { IsStatic = true };
+		Model.Types.Add(tableExtensions);
+		MakeTypeMembersNamesUnique(tableExtensions, exceptMethods: new [] { "Find" });
+	}
+
+	foreach (var schema in schemas.Values)
+	{
+		Model.Types.Add(schema.Type);
+
+		if (schema.TableExtensions.Members.Count > 0)
+		{
+			Model.Usings.Add("System.Linq");
+			schema.Type.Members.Add(schema.TableExtensions);
+		}
+	}
+
+	Tables.    Clear();
+	Procedures.Clear();
+
+	Model.SetTree();
+
+	AfterGenerateLinqToDBModel();
+}
+
+void MakeTypeMembersNamesUnique(Class type, string defaultName = "Member", params string[] exceptMethods)
+{
+	var reservedNames = new [] { type.Name };
+	if (exceptMethods != null && exceptMethods.Length > 0)
+		reservedNames = reservedNames.Concat(exceptMethods).ToArray();
+
+	MakeMembersNamesUnique(GetAllClassMembers(type.Members, exceptMethods), defaultName, reservedNames);
+}
+
+void MakeMembersNamesUnique(IEnumerable<IClassMember> members, string defaultName, params string[] reservedNames)
+{
+	LinqToDB.Common.Utils.MakeUniqueNames(
+		members,
+		reservedNames,
+		m => m is Table tbl ? (tbl.Schema != null && !tbl.IsDefaultSchema && PrefixTableMappingWithSchema ? tbl.Schema + "_" : null) + tbl.Name : (m is TypeBase t ? t.Name : ((MemberBase)m).Name),
+		(m, newName) =>
+		{
+			if (m is TypeBase t)
+				t.Name = newName;
+			else
+				((MemberBase)m).Name = newName;
+		},
+		defaultName);
+}
+
+IEnumerable<IClassMember> GetAllClassMembers(IEnumerable<IClassMember> members, params string[] exceptMethods)
+{
+	foreach (var member in members)
+	{
+		if (member is MemberGroup mg)
+			foreach (var m in GetAllClassMembers(mg.Members, exceptMethods))
+				yield return m;
+		// constructors don't have own type/flag
+		else if (member is Method method && (method.BuildType() == null || (exceptMethods != null && exceptMethods.Contains(method.Name))))
+			continue;
+		else
+			yield return member;
+	}
+}
+
+// left for backward compatibility
+string NormalizeStringName(string name)
+{
+	return ToStringLiteral(name);
+}
+
+#>
diff --git a/src/Version/LinqToDB.Templates/MultipleFiles.ttinclude b/src/Version/LinqToDB.Templates/MultipleFiles.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..4b43ba0cb45ef6415572f3758f81c3cec9fc9c93
--- /dev/null
+++ b/src/Version/LinqToDB.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<string,int> _fileNames = new Dictionary<string,int>();
+
+Func<string,string,bool> 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<string,ProjectItem>();
+	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/src/Version/LinqToDB.Templates/NotifyDataErrorInfo.ttinclude b/src/Version/LinqToDB.Templates/NotifyDataErrorInfo.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..06e72afe36bacddb7945459593de4a5bf6e93a79
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/NotifyDataErrorInfo.ttinclude
@@ -0,0 +1,133 @@
+<#
+	{
+		var beforeGenerateModel = BeforeGenerateModel;
+		BeforeGenerateModel = () =>
+		{
+			beforeGenerateModel();
+			NotifyDataErrorInfoImpl();
+		};
+	}
+#>
+<#+
+void NotifyDataErrorInfoImpl()
+{
+	foreach (var prop in  GetTreeNodes(Model).OfType<Property>().Where(p => p.CustomValidation).ToList())
+	{
+		ITree p = prop.Parent;
+
+		while (!(p is Class) && p != null)
+			p = p.Parent;
+
+		if (p != null)
+		{
+			var cl = (Class)p;
+
+			if (!cl.Interfaces.Contains("INotifyDataErrorInfo"))
+			{
+				if (!Model.Usings.Contains("System.ComponentModel")) Model.Usings.Add("System.ComponentModel");
+				if (!Model.Usings.Contains("System.Collections"))    Model.Usings.Add("System.Collections");
+				if (!Model.Usings.Contains("System.Linq"))           Model.Usings.Add("System.Linq");
+
+				cl.Interfaces.Add("INotifyDataErrorInfo");
+
+				cl.Members.Add(new MemberGroup
+				{
+					Region  = "INotifyDataErrorInfo support",
+					Members =
+					{
+						new Event(() => "EventHandler<DataErrorsChangedEventArgs>", "ErrorsChanged")
+						{
+							IsVirtual  = true,
+							Attributes = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } }
+						},
+						new Field(() => "Dictionary<string,List<string>>", "_validationErrors")
+						{
+							InitValue      = "new Dictionary<string,List<string>>()",
+							AccessModifier = AccessModifier.Private,
+							IsReadonly     = true,
+							Attributes     = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } }
+						},
+						new Method(() => "void", "AddError",
+							new Func<string>[]
+							{
+								() => "string propertyName",
+								() => "string error"
+							},
+							() => new[]
+							{
+								"List<string> errors;",
+								"",
+								"if (!_validationErrors.TryGetValue(propertyName, out errors))",
+								"{",
+									"\t_validationErrors[propertyName] = new List<string> { error };",
+								"}",
+								"else if (!errors.Contains(error))",
+								"{",
+									"\terrors.Add(error);",
+								"}",
+								"else",
+									"\treturn;",
+								"",
+								"OnErrorsChanged(propertyName);",
+							})
+						{
+							AccessModifier = AccessModifier.Public
+						},
+						new Method(() => "void", "RemoveError",
+							new Func<string>[]
+							{
+								() => "string propertyName",
+							},
+							() => new[]
+							{
+								"List<string> errors;",
+								"",
+								"if (_validationErrors.TryGetValue(propertyName, out errors) && errors.Count > 0)",
+								"{",
+									"\t_validationErrors.Clear();",
+									"\tOnErrorsChanged(propertyName);",
+								"}",
+							})
+						{
+							AccessModifier = AccessModifier.Public
+						},
+						new Method(() => "void", "OnErrorsChanged",
+							new Func<string>[]
+							{
+								() => "string propertyName",
+							},
+							() => new[]
+							{
+								"if (ErrorsChanged != null)",
+								"{",
+									"\tif (System.Windows.Deployment.Current.Dispatcher.CheckAccess())",
+										"\t\tErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));",
+									"\telse",
+										"\t\tSystem.Windows.Deployment.Current.Dispatcher.BeginInvoke(",
+											"\t\t\t() => ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)));",
+								"}",
+							})
+						{
+							AccessModifier = AccessModifier.Protected
+						},
+						new Method(() => "IEnumerable", "GetErrors",
+							new Func<string>[]
+							{
+								() => "string propertyName",
+							},
+							() => new[]
+							{
+								"List<string> errors;",
+								"return propertyName != null && _validationErrors.TryGetValue(propertyName, out errors) ? errors : null;",
+							})
+						{
+							AccessModifier = AccessModifier.Public
+						},
+						new Property(() => "bool", "HasErrors").InitGetter(() => new [] { "_validationErrors.Values.Any(e => e.Count > 0)" })
+					}
+				});
+			}
+		}
+	}
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/NotifyPropertyChanged.ttinclude b/src/Version/LinqToDB.Templates/NotifyPropertyChanged.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..49234e7df4ac27c2f5f6314587a7396bcac16a53
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/NotifyPropertyChanged.ttinclude
@@ -0,0 +1,382 @@
+<#
+	{
+		var beforeGenerateModel = BeforeGenerateModel;
+		BeforeGenerateModel = () =>
+		{
+			beforeGenerateModel();
+			NotifyPropertyChangedImpl();
+		};
+
+		SetPropertyValueAction += (obj,prop,val) =>
+		{
+			if (prop == "IsNotifying")
+				obj.IsNotifying = (bool)val;
+		};
+	}
+#><#+
+public bool ImplementNotifyPropertyChanging;
+public bool SkipNotifyPropertyChangedImplementation = false;
+
+void NotifyPropertyChangedImpl()
+{
+	foreach (Property prop in GetTreeNodes(Model).OfType<Property>().Where(p => p.IsNotifying).ToList())
+	{
+		List<IClassMember> parentMembers;
+
+		MemberGroup gr = null;
+
+		if (prop.Parent is Class)
+		{
+			var parent = (Class)prop.Parent;
+			parentMembers = parent.Members;
+		}
+		else
+		{
+			var parent = (MemberGroup)prop.Parent;
+
+			parent.IsCompact = false;
+
+			parentMembers = parent.Members;
+
+			if (parent.IsPropertyGroup)
+				gr = parent;
+		}
+
+		var name = prop.Name.Trim();
+		var type = prop.BuildType().Trim();
+
+		if (gr == null)
+		{
+			gr = new MemberGroup
+			{
+				Region          = name + " : " + type,
+				Members         = { prop },
+				IsPropertyGroup = true,
+			};
+
+			var index = parentMembers.IndexOf(prop);
+
+			parentMembers.RemoveAt(index);
+			parentMembers.Insert  (index, gr);
+		}
+
+		if (prop.IsAuto)
+		{
+			var field = new Field(() => type, "_" + ToCamelCase(name))
+			{
+				AccessModifier       = AccessModifier.Private,
+				InsertBlankLineAfter = false,
+			};
+
+			if (prop.InitValue != null)
+				field.InitValue = prop.InitValue;
+
+			gr.Members.Insert(0, field);
+
+			prop.Name        = " " + name;
+			prop.TypeBuilder = () => " " + type;
+			prop.IsAuto      = false;
+
+			if (prop.HasGetter) prop.GetBodyBuilders.Add(() => new [] { "return " + field.Name + ";" });
+			if (prop.HasSetter) prop.SetBodyBuilders.Add(() => new [] { field.Name + " = value;" });
+		}
+
+		var methods = new MemberGroup
+		{
+			Region  = "INotifyPropertyChanged support",
+			Members =
+			{
+				new Field(() => "const string", "NameOf" + name)
+				{
+					InitValue      = ToStringLiteral(name),
+					AccessModifier = AccessModifier.Public,
+				},
+				new Field(() => "PropertyChangedEventArgs", "_" + ToCamelCase(name) + "ChangedEventArgs")
+				{
+					InitValue      = "new PropertyChangedEventArgs(NameOf" + name + ")",
+					AccessModifier = AccessModifier.Private,
+					IsStatic       = true,
+					IsReadonly     = true,
+				},
+				new Method(() => "void", "On" + name + "Changed", null,
+					() => new[] { "OnPropertyChanged(_" + ToCamelCase(name) + "ChangedEventArgs);" })
+				{
+					AccessModifier = AccessModifier.Private
+				}
+			}
+		};
+
+		gr.Members.Add(methods);
+
+		if (prop.Dependents.Count == 0)
+			prop.Dependents.Add(name);
+
+		if (ImplementNotifyPropertyChanging)
+		{
+			gr.Members.Add(new MemberGroup
+			{
+				Region  = "INotifyPropertyChanging support",
+				Members =
+				{
+					new Field(() => "PropertyChangingEventArgs", "_" + ToCamelCase(name) + "ChangingEventArgs")
+					{
+						InitValue      = "new PropertyChangingEventArgs(NameOf" + name + ")",
+						AccessModifier = AccessModifier.Private,
+						IsStatic       = true,
+						IsReadonly     = true,
+					},
+					new Method(() => "void", "On" + name + "Changing", null,
+						() => new[] { "OnPropertyChanging(_" + ToCamelCase(name) + "ChangingEventArgs);" })
+					{
+						AccessModifier = AccessModifier.Private
+					}
+				}
+			});
+		}
+
+		if (prop.HasSetter)
+		{
+			var setBody = prop.BuildSetBody().Select(s => "\t" + s).ToArray();
+			prop.SetBodyBuilders.Clear();
+			prop.SetBodyBuilders.Add(() => setBody);
+
+			string getValue;
+
+			var getBody = prop.BuildGetBody().ToArray();
+			if (getBody.Length == 1 && getBody[0].StartsWith("return"))
+			{
+				getValue = getBody[0].Substring("return".Length).Trim(' ', '\t', ';');
+			}
+			else
+			{
+				getValue = name;
+			}
+
+			var insSpaces = setBody.Length > 1;
+			var n = 0;
+
+			prop.SetBodyBuilders.Insert(n++, () => new [] {"if (" + getValue + " != value)", "{" });
+
+			if (ImplementNotifyPropertyChanging)
+			{
+				foreach (var dp in prop.Dependents)
+					prop.SetBodyBuilders.Insert(n++, () => new [] { "\tOn" + dp + "Changing();" });
+				prop.SetBodyBuilders.Insert(n++, () => new [] { "" });
+			}
+
+			prop.SetBodyBuilders.Insert(n++, () => new [] { "\tBefore" + name + "Changed(value);" });
+
+			if (insSpaces)
+			{
+				prop.SetBodyBuilders.Insert(3, () => new [] { "" });
+				prop.SetBodyBuilders.Add(() => new [] { "" });
+			}
+
+			prop.SetBodyBuilders.Add(() => new [] { "\tAfter" + name + "Changed();" });
+			prop.SetBodyBuilders.Add(() => new [] { "" });
+
+			foreach (var dp in prop.Dependents)
+				prop.SetBodyBuilders.Add(() => new [] { "\tOn" + dp + "Changed();" });
+
+			prop.SetBodyBuilders.Add(() => new [] { "}" });
+
+			methods.Members.Insert(0, new MemberGroup
+			{
+				IsCompact = true,
+				Members   =
+				{
+					new Method(() => "void", "Before" + name + "Changed", new Func<string>[] { () => type + " newValue" }) { AccessModifier = AccessModifier.Partial },
+					new Method(() => "void", "After"  + name + "Changed") { AccessModifier = AccessModifier.Partial },
+				}
+			});
+		}
+
+		prop.Parent.SetTree();
+
+		ITree p = prop.Parent;
+
+		while (!(p is Class) && p != null)
+			p = p.Parent;
+
+		if (p != null)
+		{
+			var cl = (Class)p;
+
+			if (!SkipNotifyPropertyChangedImplementation && !cl.Interfaces.Contains("INotifyPropertyChanged"))
+			{
+				if (!Model.Usings.Contains("System.ComponentModel"))
+					Model.Usings.Add("System.ComponentModel");
+
+				cl.Interfaces.Add("INotifyPropertyChanged");
+
+				cl.Members.Add(new MemberGroup
+				{
+					Region  = "INotifyPropertyChanged support",
+					Members =
+					{
+						new Event(() => "PropertyChangedEventHandler", "PropertyChanged")
+						{
+							IsVirtual  = true,
+							Attributes = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } }
+						},
+						new Method(() => "void", "OnPropertyChanged", new Func<string>[] { () => "string propertyName" }, () => OnPropertyChangedBody)
+						{
+							AccessModifier = AccessModifier.Protected
+						},
+						new Method(() => "void", "OnPropertyChanged", new Func<string>[] { () => "PropertyChangedEventArgs arg" }, () => OnPropertyChangedArgBody)
+						{
+							AccessModifier = AccessModifier.Protected
+						},
+					}
+				});
+			}
+
+			if (ImplementNotifyPropertyChanging && !cl.Interfaces.Contains("INotifyPropertyChanging"))
+			{
+				if (!Model.Usings.Contains("System.ComponentModel"))
+					Model.Usings.Add("System.ComponentModel");
+
+				cl.Interfaces.Add("INotifyPropertyChanging");
+
+				cl.Members.Add(new MemberGroup
+				{
+					Region  = "INotifyPropertyChanging support",
+					Members =
+					{
+						new Event(() => "PropertyChangingEventHandler", "PropertyChanging")
+						{
+							IsVirtual  = true,
+							Attributes = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } }
+						},
+						new Method(() => "void", "OnPropertyChanging", new Func<string>[] { () => "string propertyName" }, () => OnPropertyChangingBody)
+						{
+							AccessModifier = AccessModifier.Protected
+						},
+						new Method(() => "void", "OnPropertyChanging", new Func<string>[] { () => "PropertyChangingEventArgs arg" }, () => OnPropertyChangingArgBody)
+						{
+							AccessModifier = AccessModifier.Protected
+						},
+					}
+				});
+			}
+		}
+	}
+}
+
+public string[] OnPropertyChangedBody = new[]
+{
+	"var propertyChanged = PropertyChanged;",
+	"",
+	"if (propertyChanged != null)",
+	"{",
+	"#if SILVERLIGHT",
+	"\tif (System.Windows.Deployment.Current.Dispatcher.CheckAccess())",
+	"\t\tpropertyChanged(this, new PropertyChangedEventArgs(propertyName));",
+	"\telse",
+	"\t\tSystem.Windows.Deployment.Current.Dispatcher.BeginInvoke(",
+	"\t\t\t() =>",
+	"\t\t\t{",
+	"\t\t\t\tvar pc = PropertyChanged;",
+	"\t\t\t\tif (pc != null)",
+	"\t\t\t\t\tpc(this, new PropertyChangedEventArgs(propertyName));",
+	"\t\t\t});",
+	"#else",
+	"\tpropertyChanged(this, new PropertyChangedEventArgs(propertyName));",
+	"#endif",
+	"}",
+};
+
+public string[] OnPropertyChangedArgBody = new[]
+{
+	"var propertyChanged = PropertyChanged;",
+	"",
+	"if (propertyChanged != null)",
+	"{",
+	"#if SILVERLIGHT",
+	"\tif (System.Windows.Deployment.Current.Dispatcher.CheckAccess())",
+	"\t\tpropertyChanged(this, arg);",
+	"\telse",
+	"\t\tSystem.Windows.Deployment.Current.Dispatcher.BeginInvoke(",
+	"\t\t\t() =>",
+	"\t\t\t{",
+	"\t\t\t\tvar pc = PropertyChanged;",
+	"\t\t\t\tif (pc != null)",
+	"\t\t\t\t\tpc(this, arg);",
+	"\t\t\t});",
+	"#else",
+	"\tpropertyChanged(this, arg);",
+	"#endif",
+	"}",
+};
+
+public string[] OnPropertyChangingBody = new[]
+{
+	"var propertyChanging = PropertyChanging;",
+	"",
+	"if (propertyChanging != null)",
+	"{",
+	"#if SILVERLIGHT",
+	"\tif (System.Windows.Deployment.Current.Dispatcher.CheckAccess())",
+	"\t\tpropertyChanging(this, new PropertyChangingEventArgs(propertyName));",
+	"\telse",
+	"\t\tSystem.Windows.Deployment.Current.Dispatcher.BeginInvoke(",
+	"\t\t\t() =>",
+	"\t\t\t{",
+	"\t\t\t\tvar pc = PropertyChanging;",
+	"\t\t\t\tif (pc != null)",
+	"\t\t\t\t\tpc(this, new PropertyChangingEventArgs(propertyName));",
+	"\t\t\t});",
+	"#else",
+	"\tpropertyChanging(this, new PropertyChangingEventArgs(propertyName));",
+	"#endif",
+	"}",
+};
+
+public string[] OnPropertyChangingArgBody = new[]
+{
+	"var propertyChanging = PropertyChanging;",
+	"",
+	"if (propertyChanging != null)",
+	"{",
+	"#if SILVERLIGHT",
+	"\tif (System.Windows.Deployment.Current.Dispatcher.CheckAccess())",
+	"\t\tpropertyChanging(this, arg);",
+	"\telse",
+	"\t\tSystem.Windows.Deployment.Current.Dispatcher.BeginInvoke(",
+	"\t\t\t() =>",
+	"\t\t\t{",
+	"\t\t\t\tvar pc = PropertyChanging;",
+	"\t\t\t\tif (pc != null)",
+	"\t\t\t\t\tpc(this, arg);",
+	"\t\t\t});",
+	"#else",
+	"\tpropertyChanging(this, arg);",
+	"#endif",
+	"}",
+};
+
+partial class Property
+{
+	public bool         IsNotifying;
+	public List<string> Dependents = new List<string>();
+}
+
+class NotifyingProperty : Property
+{
+	public NotifyingProperty()
+	{
+		IsNotifying = true;
+	}
+
+	public NotifyingProperty(string type, string name, params string[] dependents)
+		: base(() => type, name, null, null)
+	{
+		IsNotifying = true;
+
+		if (dependents.Length == 0)
+			Dependents.Add(name);
+		else
+			Dependents.AddRange(dependents);
+	}
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/ObsoleteAttributes.ttinclude b/src/Version/LinqToDB.Templates/ObsoleteAttributes.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..b95b0d894120fb8d42eb07cf84319f9c2e92def8
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/ObsoleteAttributes.ttinclude
@@ -0,0 +1,100 @@
+<#
+	{
+		var beforeGenerateLinqToDBModel = BeforeGenerateLinqToDBModel;
+		var afterGenerateLinqToDBModel  = AfterGenerateLinqToDBModel;
+
+		var obsoleteTables = new List<Tuple<string,string,string>>();
+
+		BeforeGenerateLinqToDBModel = () =>
+		{
+			beforeGenerateLinqToDBModel();
+
+			foreach (var table in Tables.Values)
+			{
+				var idx = table.Description.IndexOf("[Obsolete");
+
+				if (idx >= 0)
+				{
+					var idx2 = table.Description.IndexOf(']', idx);
+
+					if (idx2 > idx)
+					{
+						var text = table.Description.Substring(idx + 1, idx2 - idx - 1);
+						var attr = new Attribute(text);
+						var info = Tuple.Create(table.Schema, table.Name, text);
+
+						if (obsoleteTables.All(a => a != info))
+							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)
+					{
+						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.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<MemberBase>()
+					.Where(t => t.BuildType() != null)
+					.Where(t => t.BuildType() == name || t.BuildType().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/src/Version/LinqToDB.Templates/PluralizationService.ttinclude b/src/Version/LinqToDB.Templates/PluralizationService.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..2bed1d6fe7c818c122b539e4f88a5acb1486186f
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/PluralizationService.ttinclude
@@ -0,0 +1,185 @@
+<#@ assembly name="System.Data.Entity.Design"                          #>
+<#@ import namespace="System.Data.Entity.Design.PluralizationServices" #>
+<#
+	{
+		ToPlural   = Pluralization.ToPlural;
+		ToSingular = Pluralization.ToSingular;
+	}
+#>
+<#+
+static class Pluralization
+{
+	public static string CultureInfo = "en";
+
+	static PluralizationService _service;
+
+	public static Dictionary<string,string> Dictionary = new Dictionary<string,string>
+	{
+		{ "access",       "accesses"     }, { "afterlife",    "afterlives"   }, { "alga",         "algae"        },
+		{ "alumna",       "alumnae"      }, { "alumnus",      "alumni"       }, { "analysis",     "analyses"     },
+		{ "antenna",      "antennae"     }, { "appendix",     "appendices"   }, { "axis",         "axes"         },
+		{ "bacillus",     "bacilli"      }, { "basis",        "bases"        }, { "Bedouin",      "Bedouin"      },
+		{ "cactus",       "cacti"        }, { "calf",         "calves"       }, { "cherub",       "cherubim"     },
+		{ "child",        "children"     }, { "cod",          "cod"          }, { "cookie",       "cookies"      },
+		{ "criterion",    "criteria"     }, { "curriculum",   "curricula"    }, { "data",         "data"         },
+		{ "deer",         "deer"         }, { "diagnosis",    "diagnoses"    }, { "die",          "dice"         },
+		{ "dormouse",     "dormice"      }, { "elf",          "elves"        }, { "elk",          "elk"          },
+		{ "erratum",      "errata"       }, { "esophagus",    "esophagi"     }, { "fauna",        "faunae"       },
+		{ "fish",         "fish"         }, { "flora",        "florae"       }, { "focus",        "foci"         },
+		{ "foot",         "feet"         }, { "formula",      "formulae"     }, { "fundus",       "fundi"        },
+		{ "fungus",       "fungi"        }, { "genie",        "genii"        }, { "genus",        "genera"       },
+		{ "goose",        "geese"        }, { "grouse",       "grouse"       }, { "hake",         "hake"         },
+		{ "half",         "halves"       }, { "headquarters", "headquarters" }, { "hippo",        "hippos"       },
+		{ "hippopotamus", "hippopotami"  }, { "hoof",         "hooves"       }, { "housewife",    "housewives"   },
+		{ "hypothesis",   "hypotheses"   }, { "index",        "indices"      }, { "info",         "info"         },
+		{ "jackknife",    "jackknives"   },
+		{ "knife",        "knives"       }, { "labium",       "labia"        }, { "larva",        "larvae"       },
+		{ "leaf",         "leaves"       }, { "life",         "lives"        }, { "loaf",         "loaves"       },
+		{ "louse",        "lice"         }, { "magus",        "magi"         }, { "man",          "men"          },
+		{ "memorandum",   "memoranda"    }, { "midwife",      "midwives"     }, { "millennium",   "millennia"    },
+		{ "moose",        "moose"        }, { "mouse",        "mice"         }, { "nebula",       "nebulae"      },
+		{ "neurosis",     "neuroses"     }, { "nova",         "novas"        }, { "nucleus",      "nuclei"       },
+		{ "oesophagus",   "oesophagi"    }, { "offspring",    "offspring"    }, { "ovum",         "ova"          },
+		{ "ox",           "oxen"         }, { "papyrus",      "papyri"       }, { "passerby",     "passersby"    },
+		{ "penknife",     "penknives"    }, { "person",       "people"       }, { "phenomenon",   "phenomena"    },
+		{ "placenta",     "placentae"    }, { "pocketknife",  "pocketknives" }, { "process",      "processes"    },
+		{ "pupa",         "pupae"        }, { "radius",       "radii"        }, { "reindeer",     "reindeer"     },
+		{ "retina",       "retinae"      }, { "rhinoceros",   "rhinoceros"   }, { "roe",          "roe"          },
+		{ "salmon",       "salmon"       }, { "scarf",        "scarves"      }, { "self",         "selves"       },
+		{ "seraph",       "seraphim"     }, { "series",       "series"       }, { "sheaf",        "sheaves"      },
+		{ "sheep",        "sheep"        }, { "shelf",        "shelves"      }, { "species",      "species"      },
+		{ "spectrum",     "spectra"      }, { "status",       "status"       }, { "stimulus",     "stimuli"      },
+		{ "stratum",      "strata"       }, { "supernova",    "supernovas"   }, { "swine",        "swine"        },
+		{ "terminus",     "termini"      }, { "thesaurus",    "thesauri"     }, { "thesis",       "theses"       },
+		{ "thief",        "thieves"      }, { "trout",        "trout"        }, { "vulva",        "vulvae"       },
+		{ "wife",         "wives"        }, { "wildebeest",   "wildebeest"   }, { "wolf",         "wolves"       },
+		{ "woman",        "women"        }, { "yen",          "yen"          },
+	};
+
+	static string GetLastWord(string str)
+	{
+		if (string.IsNullOrWhiteSpace(str))
+			return string.Empty;
+
+		var i = str.Length - 1;
+		var isLower = char.IsLower(str[i]);
+
+		while (i > 0 && char.IsLetter(str[i - 1]) && char.IsLower(str[i - 1]) == isLower)
+			i--;
+
+		return str.Substring(isLower && i > 0 && char.IsLetter(str[i - 1]) ? i - 1 : i);
+	}
+
+	public static string ToPlural(string str)
+	{
+		if (_service == null)
+			_service = PluralizationService.CreateService(System.Globalization.CultureInfo.GetCultureInfo(CultureInfo));
+
+		var word = GetLastWord(str);
+
+		string newWord;
+
+		if (!Dictionary.TryGetValue(word.ToLower(), out newWord))
+			newWord = _service.IsPlural(word) ? word : _service.Pluralize(word);
+
+		if (string.Compare(word, newWord, true) != 0)
+		{
+			if (char.IsUpper(word[0]))
+				newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1).ToLower();
+
+			return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord;
+		}
+
+		return str;
+	}
+
+	public static string ToSingular(string str)
+	{
+		if (_service == null)
+			_service = PluralizationService.CreateService(System.Globalization.CultureInfo.GetCultureInfo(CultureInfo));
+
+		var word = GetLastWord(str);
+
+		var newWord =
+			Dictionary
+				.Where(dic => string.Compare(dic.Value, word, true) == 0)
+				.Select(dic => dic.Key)
+				.FirstOrDefault()
+			??
+			(_service.IsSingular(word) ? word : _service.Singularize(word));
+
+		if (string.Compare(word, newWord, true) != 0)
+		{
+			if (char.IsUpper(word[0]))
+				newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1);
+
+			return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord;
+		}
+
+		return str;
+	}
+
+	static string GetLastWordVersion1(string str)
+	{
+		if (string.IsNullOrWhiteSpace(str))
+			return string.Empty;
+
+		var i       = str.Length - 1;
+		var isLower = char.IsLower(str[i]);
+
+		while (i > 0 && char.IsLower(str[i-1]) == isLower)
+			i--;
+
+		return str.Substring(isLower && i > 0 ? i - 1 : i);
+	}
+
+	public static string ToPluralVersion1(string str)
+	{
+		if (_service == null)
+			_service = PluralizationService.CreateService(System.Globalization.CultureInfo.GetCultureInfo(CultureInfo));
+
+		var word = GetLastWordVersion1(str);
+
+		string newWord;
+
+		if (!Dictionary.TryGetValue(word.ToLower(), out newWord))
+			newWord = _service.IsPlural(word) ? word : _service.Pluralize(word);
+
+		if (string.Compare(word, newWord, true) != 0)
+		{
+			if (char.IsUpper(word[0]))
+				newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1);
+
+			return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord;
+		}
+
+		return str;
+	}
+
+	public static string ToSingularVersion1(string str)
+	{
+		if (_service == null)
+			_service = PluralizationService.CreateService(System.Globalization.CultureInfo.GetCultureInfo(CultureInfo));
+
+		var word = GetLastWordVersion1(str);
+
+		var newWord =
+			Dictionary
+				.Where(dic => string.Compare(dic.Value, word, true) == 0)
+				.Select(dic => dic.Key)
+				.FirstOrDefault()
+			??
+			(_service.IsSingular(word) ? word : _service.Singularize(word));
+
+		if (string.Compare(word, newWord, true) != 0)
+		{
+			if (char.IsUpper(word[0]))
+				newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1);
+
+			return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord;
+		}
+
+		return str;
+	}
+}
+#>
diff --git a/src/Version/LinqToDB.Templates/README.md b/src/Version/LinqToDB.Templates/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0c16bb299841c238e9838723a22350d31fb0800f
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/README.md
@@ -0,0 +1,383 @@
+# T4 Models
+
+T4 models are used to generate POCO's C# code using your database structure.
+
+## Installation
+
+Firstly you should install one of tools packages into your project:
+
+`Install-Package linq2db.XXX`
+
+Where XXX is one of supported databases, for example:
+
+`Install-Package linq2db.SqlServer`
+
+This also will install needed linq2db packages:
+
+* linq2db.t4models
+* linq2db 
+
+But **not** data provider packages (install them only if needed to compile your project, T4 models ships it's own data provider assemblies).
+
+### .Net Core specific
+
+Because of .Net Core projects do not support NuGet content files all stuff is not copied into project's folder, so to run T4 templates you'll need:
+
+* open `$(SolutionDir).tools\linq2db.t4models` in Explorer 
+* copy `CopyMe.XXX.Core.tt.txt` to your project's folder or subfolder, then you should use it instead of `CopyMe.XXX.tt.txt`
+
+## Running
+
+After package installing you will see new `LinqToDB.Templates` folder in your project, this folder contains all needed T4 stuff to generate your model. Also would be created new folder in tour solution: `$(SolutionDir).tools\linq2db.t4models`, it is used to store and link assemblies, needed for generation (linq2db.dll and data provider assemblies).
+
+To create a data model template take a look at one of the CopyMe.XXX.tt.txt file in your LinqToDB.Templates project folder. Copy this file to needed project location and rename it, like `MyModel.tt`
+
+There are few main steps in this file:
+
+1. Configuring generation process (read below)
+1. Loading metadata - this is a call to `LoadMatadata()` function - it connects to your database and fetches all needed metadata (table structure, views, and so on)
+1. Customizing generation process (read below)
+1. Calling `GenerateModel()` - this will run model generation 
+
+## Configuring schema load process
+
+Use the following initialization **before** you call the `LoadMetadata()` method.
+
+All schema load functionality configured using `GetSchemaOptions` property of [`LinqToDB.SchemaProvider.GetSchemaOptions`](https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/SchemaProvider/GetSchemaOptions.cs) type. Check this class for all available options.
+
+All loaded schema information is used for mappings generation, so if you want to limit generated mappings, it is the best place to do it.
+
+```cs
+// Enables loading of tables and views information
+GetSchemaOptions.GetTables             = true;
+// Enables loading of functions and procedures information
+GetSchemaOptions.GetProcedures         = true;
+// Enables use of System.Char type in generated model for text types
+// with length 1 instead of System.String
+GetSchemaOptions.GenerateChar1AsString = false;
+
+// (string[]) List of schemas to select.
+// Option applied only if is is not empty
+GetSchemaOptions.IncludedSchemas = null;
+// (string[]) List of schemas to exclude from select.
+// Option applied only if is is not empty
+GetSchemaOptions.ExcludedSchemas = null;
+
+// Option makes sense only for providers that return schema for several databases
+// (string[]) List of databases/catalogs to select.
+// Option applied only if is is not empty
+GetSchemaOptions.IncludedCatalogs = null;
+// Option makes sense only for providers that return schema for several databases
+// (string[]) List of databases/catalogs to exclude from select.
+// Option applied only if is is not empty
+GetSchemaOptions.ExcludedCatalogs = null;
+
+// Comparer, used for IncludedSchemas/ExcludedSchemas/IncludedCatalogs/ExcludedCatalogs lookups
+StringComparer                    = StringComparer.OrdinalIgnoreCase;
+
+// Custom filter for procedure/function result schema loader.
+// Can be used to exclude schema load for functions, that generate error during schema load
+// Also check GenerateProcedureErrors option below
+// ProcedureSchema type:
+// https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/SchemaProvider/ProcedureSchema.cs
+GetSchemaOptions.LoadProcedure     = (ProcedureSchema p) => true;
+
+// type: Func<ForeignKeySchema, string>
+// Defines custom association naming logic
+// https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/SchemaProvider/ForeignKeySchema.cs
+GetSchemaOptions.GetAssociationMemberName = null;
+
+// Procedures load progress reporting callback
+// Not applicable for T4 templates
+GetSchemaOptions.ProcedureLoadingProgress = (int total, int current) => {};
+```
+
+## Configuring generation process
+
+Use the following initialization **before** you call the `LoadMetadata()` method.
+
+```cs
+/* Global/generic options */
+// Namespace to use for generated model
+NamespaceName                  = "DataModels";
+
+/* Data context configuration */
+// (string) Name of base class for generated data context class.
+// Default: LinqToDB.Data.DataConnection.
+BaseDataContextClass           = null;
+// (string) Name of data context class.
+// Default: <DATABASE_NAME> + "DB"
+DataContextName                = null;
+// Enables generation of constructors for data context class.
+// Disabling could be usefull if you need to have custom implementation
+// of constructors in partial class
+GenerateConstructors          = true;               // Enforce generating DataContext constructors.
+// (string) Defines name of default configuration to use with default data context constructor
+DefaultConfiguration          = null;
+
+/* Schemas configuration */
+// Enables generation of mappings for each schema in separate type
+GenerateSchemaAsType            = false;
+// Contains mapping of schema name to corresponding schema class name
+// By default is empty and class name generated from schema name
+// Requires GenerateSchemaAsType=true set
+SchemaNameMapping               = Dictionary<string,string>();
+// Suffix, added to schema class name
+// Requires GenerateSchemaAsType=true set
+SchemaNameSuffix                = "Schema"
+// Name of data context class for schema.
+// Requires GenerateSchemaAsType=true set
+SchemaDataContextTypeName       = "DataContext"
+
+/* Table mappings configuration */
+// (string) Specify base class (or comma-separated list of class and/or interfaces) for table mappings
+BaseEntityClass               = null;
+// Enables generation of TableAttribute.Database property using database name, returned by schema loader
+GenerateDatabaseName          = false;
+// Enables generation of TableAttribute.Database property with provided name value.
+// (string) If set, overrides GenerateDatabaseName behavior
+DatabaseName                  = null;
+// Enables generation of TableAttribute.Schema property for default schema
+IncludeDefaultSchema          = true;
+// Enables generation of mappings for views
+GenerateViews                 = true;
+// Enables prefixing mapping classes for tables in non-default schema with schema name
+// E.g. MySchema.MyTable -> MySchema_MyTable
+// Applicable only if GenerateSchemaAsType = false
+PrefixTableMappingWithSchema  = true;
+
+/* Columns comfiguration */
+// Enables compact generation of column properties
+IsCompactColumns              = true;
+// Enables compact generation of aliased column properties
+IsCompactColumnAliases              = true;
+// Enables generation of DataType, Length, Precision and Scale properties of ColumnAttribute.
+// Could be overriden (except DataType) by options below
+GenerateDataTypes                   = false;
+// (boolean) Enables or disables generation of ColumnAttribute.Length property.
+// If null, GenerateDataTypes value is used
+GenerateLengthProperty              = null;
+// (boolean) Enables or disables generation of ColumnAttribute.Precision property.
+// If null, GenerateDataTypes value is used
+GeneratePrecisionProperty           = null;
+// (boolean) Enables or disables generation of ColumnAttribute.Scale property.
+// If null, GenerateDataTypes value is used
+GenerateScaleProperty               = null;
+// Enables generation of ColumnAttribute.DbType property.
+GenerateDbTypes                     = false;
+// Enables generation of ObsoleteAttribute for column aliases
+GenerateObsoleteAttributeForAliases = false;
+
+/* Associations configuration */
+// Defines type template for one-to-many association, when it is generated as a member of table mapping.
+// Some other options: "{0}[]", "List<{0}>".
+OneToManyAssociationType      = "IEnumerable<{0}>";
+// Enables generation of associations in table mappings
+GenerateAssociations          = true;
+// Enables generation of back side of association. Applies to both table mapping members and extension
+// associations
+GenerateBackReferences        = true;
+// Enables generation of associations as extension methods for related table mapping classes
+GenerateAssociationExtensions = false;
+// Defines method to generate name for "one" side of association
+Func<ForeignKey, string> GetAssociationExtensionSinglularName
+    = GetAssociationExtensionSinglularNameDefault;
+// Defines method to generate name for "many" side of association
+Func<ForeignKey, string> GetAssociationExtensionPluralName
+    = GetAssociationExtensionPluralNameDefault;
+
+/* Procedures and functions configuration */
+// Enables use of existing table mappings for procedures and functions that return same results as
+// defined by mapping
+ReplaceSimilarTables          = true;
+// If enabled, procedure schema load error will be generated as #error directive and fail build
+// of output file. Useful for initial generation to highlight places, that require review or
+// additional hints for schema loader
+// Also check GetSchemaOptions.LoadProcedure option above
+GenerateProcedureErrors       = true;
+// If enabled, methods for procedures that return table will be generated with List<T> return type and
+// IMPORTANT: this will lead to load of all procedure results into list and could lead
+// to performance issues on big results
+GenerateProcedureResultAsList = false;
+
+/* Other generated functionality */
+// Enables generation of Find(pk fields) extension methods for record selection by primary key value
+GenerateFindExtensions        = true;
+
+/* Pluralization services */
+// Enables pluralization of table mapping classes
+PluralizeClassNames                 = false;
+// Enables singularization of table mapping classes
+SingularizeClassNames               = true;
+// Enables pluralization of ITable<> properties in data context
+PluralizeDataContextPropertyNames   = true;
+// Enables singularization of ITable<> properties in data context
+SingularizeDataContextPropertyNames = false;
+
+/* Naming configuration */
+// Enables normalization of of type and member names.
+// Default normalization removes underscores and capitalize first letter.
+// Could be overriden using ToValidName option below.
+NormalizeNames                                 = false;
+// Defines logic to convert type/member name, derived from database object name, to C# identifier.
+Func<string, bool, string> ToValidName         = ToValidNameDefault;
+// Makes C# identifier valid by removing unsupported symbols and calling ToValidName
+Func<string, bool, string> ConvertToCompilable = ConvertToCompilableDefault;
+```
+
+## Provider specific options
+
+### SQL Server
+
+```cs
+// Enables generation of extensions for Free Text Search
+bool GenerateSqlServerFreeText = true;
+```
+
+### PostgreSQL
+
+```cs
+// Enables generation of case-sensitive names of database objects
+bool GenerateCaseSensitiveNames = false;
+```
+
+### Sybase
+
+```cs
+// Enables generation of Sybase sysobjects tables
+bool GenerateSybaseSystemTables = false;
+```
+
+## Example of generation process customization
+
+Use the following code to modify your model **before** you call the `GenerateModel()` method.
+
+```c#
+// Replaces table mapping class name
+GetTable("Person").TypeName  = "MyName";
+// Sets base class & interface for mapping class
+GetTable("Person").BaseClass = "PersonBase, IId";
+
+// Replaces property name for column PersonID of Person table with ID.
+GetColumn("Person", "PersonID")    .MemberName   = "ID";
+// Sets [Column(SkipOnUpdate=true)].
+// Same logic can be used for other column options
+GetColumn("Person", "PasswordHash").SkipOnUpdate = true;
+// Change column property type
+GetColumn("Person", "Gender")      .Type         = "global::Model.Gender";
+
+// Replaces association property name
+GetFK("Orders", "FK_Orders_Customers").MemberName      = "Customers";
+// Changes association type
+GetFK("Orders", "FK_Orders_Customers").AssociationType = AssociationType.OneToMany;
+
+SetTable(string tableName,
+	string TypeName = null,
+	string DataContextPropertyName = null)
+
+	.Column(string columnName, string MemberName = null, string Type = null, bool? IsNullable = null)
+	.FK    (string fkName,     string MemberName = null, AssociationType? AssociationType = null)
+	;
+
+// Adds extra namespace to usings
+Model.Usings.Add("MyNamespace");
+
+// Replaces all property names for columns where name is '<TableName>' + 'ID' with 'ID'.
+foreach (var t in Tables.Values)
+	foreach (var c in t.Columns.Values)
+		if (c.IsPrimaryKey && c.MemberName == t.TypeName + "ID")
+			c.MemberName = "ID";
+```
+
+## Useful members and data structures
+
+```c#
+Dictionary<string,Table>     Tables     = new Dictionary<string,Table>    ();
+Dictionary<string,Procedure> Procedures = new Dictionary<string,Procedure>();
+
+Table      GetTable     (string name);
+Procedure  GetProcedure (string name);
+Column     GetColumn    (string tableName, string columnName);
+ForeignKey GetFK        (string tableName, string fkName);
+ForeignKey GetForeignKey(string tableName, string fkName);
+
+public class Table
+{
+	public string Schema;
+	public string TableName;
+	public string DataContextPropertyName;
+	public bool   IsView;
+	public string Description;
+	public string AliasPropertyName;
+	public string AliasTypeName;
+	public string TypeName;
+
+	public Dictionary<string,Column>     Columns;
+	public Dictionary<string,ForeignKey> ForeignKeys;
+}
+
+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;
+}
+
+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;
+	public AssociationType  AssociationType;
+}
+
+public partial class Procedure : Method
+{
+	public string          Schema;
+	public string          ProcedureName;
+	public bool            IsFunction;
+	public bool            IsTableFunction;
+	public bool            IsDefaultSchema;
+
+	public Table           ResultTable;
+	public Exception       ResultException;
+	public List<Table>     SimilarTables;
+	public List<Parameter> ProcParameters;
+}
+
+public class Parameter
+{
+	public string   SchemaName;
+	public string   SchemaType;
+	public bool     IsIn;
+	public bool     IsOut;
+	public bool     IsResult;
+	public int?     Size;
+	public string   ParameterName;
+	public string   ParameterType;
+	public Type     SystemType;
+	public string   DataType;
+}
+```
diff --git a/src/Version/LinqToDB.Templates/T4Model.ttinclude b/src/Version/LinqToDB.Templates/T4Model.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..d164aaef9a42fd1d4ad0d5e12b738f916af133c9
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/T4Model.ttinclude
@@ -0,0 +1,1564 @@
+<#@ assembly name="System.Core"                   #>
+<#@ import namespace="System"                     #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Linq"                #>
+<#@ import namespace="System.Text"                #>
+<#+
+static Action<GeneratedTextTransformation,string> WriteComment    = (tt,s) => tt.WriteLine("//{0}", s);
+
+Action BeforeGenerateModel = () => {};
+
+bool GenerateProcedureErrors = true;
+
+void GenerateModel()
+{
+	Model.SetTree();
+
+	if (GenerationEnvironment.Length > 0 && GenerationEnvironment.ToString().Trim().Length == 0)
+		GenerationEnvironment.Length = 0;
+
+	WriteComment(this, "---------------------------------------------------------------------------------------------------");
+	WriteComment(this, " <auto-generated>");
+	WriteComment(this, "    This code was generated by T4Model template for T4 (https://github.com/linq2db/linq2db).");
+	WriteComment(this, "    Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.");
+	WriteComment(this, " </auto-generated>");
+	WriteComment(this, "---------------------------------------------------------------------------------------------------");
+
+	WriteLine("");
+	WriteLine("#pragma warning disable 1591");
+	WriteLine("");
+	
+	BeforeGenerateModel();
+
+	Model.Render(this);
+
+	WriteLine("");
+	WriteLine("#pragma warning restore 1591");
+
+}
+
+void Trim()
+{
+	var arr = new[] { '\r', '\n', ' ' };
+	while (GenerationEnvironment.Length > 0 && arr.Contains(GenerationEnvironment[GenerationEnvironment.Length - 1]))
+		GenerationEnvironment.Length--;
+
+	WriteLine("");
+}
+
+static Action<GeneratedTextTransformation,string> WriteUsing = (tt,s) => tt.WriteLine("using {0};", s);
+
+void RenderUsings(List<string> usings)
+{
+	var q =
+		from ns in usings.Distinct()
+		group ns by ns.Split('.')[0];
+
+	var groups =
+		(from ns in q where ns.Key == "System"                select ns).Concat
+		(from ns in q where ns.Key != "System" orderby ns.Key select ns);
+
+	foreach (var gr in groups)
+	{
+		foreach (var ns in from s in gr orderby s select s)
+			WriteUsing(this, ns);
+
+		WriteLine("");
+	}
+
+	Trim();
+}
+
+// Base data types.
+//
+public interface ITree
+{
+	ITree              Parent { get; set; }
+	IEnumerable<ITree> GetNodes();
+	void               SetTree();
+}
+
+ModelSource Model = new ModelSource();
+
+public partial class ModelSource : ITree
+{
+	public int CurrentNamespace = 0;
+
+	public List<string>    Usings     = new List<String>    { "System"        };
+	public List<Namespace> Namespaces = new List<Namespace> { new Namespace() };
+
+	public Namespace      Namespace { get { return Namespaces[CurrentNamespace];       } }
+	public List<TypeBase> Types     { get { return Namespaces[CurrentNamespace].Types; } }
+
+	public virtual void Render(GeneratedTextTransformation tt)
+	{
+		tt.RenderUsings(Usings);
+		tt.WriteLine("");
+
+		foreach (var nm in Namespaces)
+		{
+			nm.Render(tt);
+			tt.WriteLine("");
+		}
+
+		tt.Trim();
+	}
+
+	public ITree              Parent     { get; set; }
+	public IEnumerable<ITree> GetNodes() { return Namespaces; }
+
+	public void SetTree()
+	{
+		foreach (var ch in GetNodes())
+		{
+			ch.Parent = this;
+			ch.SetTree();
+		}
+	}
+}
+
+static Action<GeneratedTextTransformation,string> WriteBeginNamespace = (tt,s) => { tt.WriteLine("namespace {0}", s); tt.WriteLine("{"); };
+static Action<GeneratedTextTransformation>        WriteEndNamespace   =  tt    => tt.WriteLine("}");
+
+public partial class Namespace : ITree
+{
+	public string         Name;
+	public List<TypeBase> Types  = new List<TypeBase>();
+	public List<string>   Usings = new List<string>();
+
+	public virtual void Render(GeneratedTextTransformation tt)
+	{
+		if (!string.IsNullOrEmpty(Name))
+		{
+			WriteBeginNamespace(tt, Name);
+			tt.PushIndent("\t");
+		}
+
+		tt.RenderUsings(Usings);
+
+		foreach (var t in Types)
+		{
+			t.Render(tt);
+			tt.WriteLine("");
+		}
+
+		tt.Trim();
+
+		if (!string.IsNullOrEmpty(Name))
+		{
+			tt.PopIndent();
+			WriteEndNamespace(tt);
+		}
+	}
+
+	public ITree              Parent     { get; set; }
+	public IEnumerable<ITree> GetNodes() { return Types; }
+
+	public void SetTree()
+	{
+		foreach (var ch in GetNodes())
+		{
+			ch.Parent = this;
+			ch.SetTree();
+		}
+	}
+}
+
+public interface IClassMember : ITree
+{
+}
+
+public enum AccessModifier
+{
+	Public,
+	Protected,
+	Internal,
+	Private,
+	Partial
+}
+
+public abstract partial class TypeBase : IClassMember
+{
+	public AccessModifier  AccessModifier = AccessModifier.Public;
+	public string          Name;
+	public bool            IsPartial  = true;
+	public List<string>    Comment    = new List<string>();
+	public List<Attribute> Attributes = new List<Attribute>();
+	public string          Conditional;
+
+	public abstract void Render(GeneratedTextTransformation tt);
+
+	protected virtual void BeginConditional(GeneratedTextTransformation tt)
+	{
+		if (Conditional != null)
+		{
+			tt.RemoveSpace();
+			tt.WriteLine("#if " + Conditional);
+			tt.WriteLine("");
+		}
+	}
+
+	protected virtual void EndConditional(GeneratedTextTransformation tt)
+	{
+		if (Conditional != null)
+		{
+			tt.RemoveSpace();
+			tt.WriteLine("");
+			tt.RemoveSpace();
+			tt.WriteLine("#endif");
+		}
+	}
+
+	public          ITree              Parent { get; set; }
+	public abstract IEnumerable<ITree> GetNodes();
+	public abstract void               SetTree ();
+}
+
+static Action<GeneratedTextTransformation,Class> WriteBeginClass = (tt,cl) =>
+{
+	tt.Write(cl.AccessModifier.ToString().ToLower() + " ");
+	if (cl.IsStatic)  tt.Write("static ");
+	if (cl.IsPartial) tt.Write("partial ", cl.Name);
+	tt.Write("class {0}{1}", cl.Name, cl.GenericArguments.Count > 0 ? $"<{string.Join(", ", cl.GenericArguments)}>" : string.Empty);
+
+	if (!string.IsNullOrEmpty(cl.BaseClass) || cl.Interfaces.Count > 0)
+	{
+		var arr = new[] { cl.BaseClass }.Concat(cl.Interfaces)
+			.Where(n => n != null)
+			.ToArray();
+
+		tt.Write(" : ");
+		tt.Write(string.Join(", ", arr));
+	}
+
+	tt.WriteLine("");
+	tt.WriteLine("{");
+};
+
+static Action<GeneratedTextTransformation> WriteEndClass = tt => tt.WriteLine("}");
+
+public partial class Class : TypeBase
+{
+	public string             BaseClass;
+	public List<string>       GenericArguments = new List<string>();
+	public bool               IsStatic         = false;
+	public List<string>       Interfaces       = new List<string>();
+	public List<IClassMember> Members          = new List<IClassMember>();
+
+	public Class()
+	{
+	}
+
+	public Class(string name, params IClassMember[] members)
+	{
+		Name = name;
+		Members.AddRange(members);
+	}
+
+	public override void Render(GeneratedTextTransformation tt)
+	{
+		BeginConditional(tt);
+
+		foreach (var c in Comment)
+			tt.WriteLine("//" + c);
+
+		if (Attributes.Count > 0)
+		{
+			var aa = Attributes.Where(a => !a.IsSeparated).ToList();
+
+			if (aa.Count > 0)
+			{
+				tt.Write("[");
+
+				for (var i = 0; i < aa.Count; i++)
+				{
+					if (i > 0) SkipSpacesAndInsert(tt, ", ");
+					aa[i].Render(tt);
+				}
+
+				tt.WriteLine("]");
+			}
+
+			aa = Attributes.Where(a => a.IsSeparated).ToList();
+
+			foreach (var a in aa)
+			{
+				tt.Write("[");
+				a.Render(tt);
+				tt.WriteLine("]");
+			}
+		}
+
+		WriteBeginClass(tt, this);
+		tt.PushIndent("\t");
+
+		foreach (var cm in Members)
+		{
+			if (cm is MemberBase)
+			{
+				var m = (MemberBase)cm;
+
+				if (!(m is MemberGroup))
+					m.BeginConditional(tt, false);
+
+				foreach (var c in m.Comment)
+					WriteComment(tt, c);
+
+				if (m.Attributes.Count > 0)
+				{
+					var q =
+						from a in m.Attributes
+						group a by a.Conditional ?? "";
+
+					foreach (var g in q)
+					{
+						if (g.Key.Length > 0)
+						{
+							tt.RemoveSpace();
+							tt.WriteLine("#if " + g.Key);
+						}
+
+						var attrs = g.ToList();
+
+						tt.Write("[");
+
+						for (var i = 0; i < attrs.Count; i++)
+						{
+							if (i > 0) SkipSpacesAndInsert(tt, ", ");
+							attrs[i].Render(tt);
+						}
+
+						tt.WriteLine("]");
+
+						if (g.Key.Length > 0)
+						{
+							tt.RemoveSpace();
+							tt.WriteLine("#endif");
+						}
+					}
+				}
+
+				m.Render(tt, false);
+				if (m.InsertBlankLineAfter)
+					tt.WriteLine("");
+
+				if (!(m is MemberGroup))
+					m.EndConditional(tt, false);
+			}
+			else if (cm is TypeBase)
+			{
+				var t = (TypeBase)cm;
+
+				t.Render(tt);
+				tt.WriteLine("");
+			}
+		}
+
+		tt.Trim();
+
+		tt.PopIndent();
+		WriteEndClass(tt);
+
+		EndConditional(tt);
+	}
+
+	public override IEnumerable<ITree> GetNodes()
+	{
+		return Members;
+	}
+
+	public override void SetTree()
+	{
+		foreach (var ch in GetNodes())
+		{
+			ch.Parent = this;
+			ch.SetTree();
+		}
+	}
+}
+
+public abstract partial class MemberBase : IClassMember
+{
+	public string          ID;
+	public AccessModifier  AccessModifier = AccessModifier.Public;
+	public string          Name;
+	public Func<string>    TypeBuilder;
+	public List<string>    Comment = new List<string>();
+	public string          EndLineComment;
+	public List<Attribute> Attributes = new List<Attribute>();
+	public bool            InsertBlankLineAfter = true;
+	public string          Conditional;
+
+	public int AccessModifierLen;
+	public int ModifierLen;
+	public int TypeLen;
+	public int NameLen;
+	public int ParamLen;
+	public int BodyLen;
+
+	public string Type
+	{
+		get { return TypeBuilder?.Invoke(); }
+		set { TypeBuilder = () => value;    }
+	}
+
+	public string BuildType() { return TypeBuilder?.Invoke(); }
+
+	public virtual  int  CalcModifierLen() { return 0; }
+	public abstract int  CalcBodyLen    ();
+	public virtual  int  CalcParamLen   () { return 0; }
+	public abstract void Render         (GeneratedTextTransformation tt, bool isCompact);
+
+	public virtual void BeginConditional(GeneratedTextTransformation tt, bool isCompact)
+	{
+		if (Conditional != null)
+		{
+			tt.RemoveSpace();
+			tt.WriteLine("#if " + Conditional);
+			if (!isCompact)
+				tt.WriteLine("");
+		}
+	}
+
+	public virtual void EndConditional(GeneratedTextTransformation tt, bool isCompact)
+	{
+		if (Conditional != null)
+		{
+			tt.RemoveSpace();
+			tt.WriteLine("#endif");
+			if (!isCompact)
+				tt.WriteLine("");
+		}
+	}
+
+	public         ITree              Parent     { get; set; }
+	public virtual IEnumerable<ITree> GetNodes() { return Enumerable.Empty<ITree>(); }
+	public virtual void               SetTree () {}
+}
+
+static Action<GeneratedTextTransformation,string> BeginRegion = (tt,s) => { tt.WriteLine("#region {0}", s); };
+static Action<GeneratedTextTransformation>        EndRegion   = (tt)   => { tt.WriteLine("#endregion");     };
+
+public partial class MemberGroup : MemberBase
+{
+	public string             Region;
+	public bool               IsCompact;
+	public bool               IsPropertyGroup;
+	public List<IClassMember> Members = new List<IClassMember>();
+	public List<string>       Errors  = new List<string>();
+
+	public override int  CalcBodyLen() { return 0; }
+
+	public override void Render(GeneratedTextTransformation tt, bool isCompact)
+	{
+		if (!string.IsNullOrEmpty(Region))
+		{
+			BeginRegion(tt, Region);
+			tt.WriteLine("");
+		}
+
+		BeginConditional(tt, isCompact);
+
+		if (Errors.Count > 0 && tt.GenerateProcedureErrors)
+		{
+			tt.RemoveSpace();
+			WriteComment(tt, " Use 'GenerateProcedureErrors=false' to disable errors.");
+			foreach (var error in Errors)
+			{
+				tt.Error(error);
+
+				foreach (var e in error.Split('\n'))
+				{
+					tt.RemoveSpace();
+					tt.WriteLine("#error " + e.Trim('\r'));
+				}
+			}
+
+			tt.WriteLine("");
+		}
+
+		if (IsCompact)
+		{
+			var allMembers = GetTreeNodes(this).OfType<MemberBase>().Where(m => !(m is MemberGroup)).ToList();
+
+			if (allMembers.Count > 0)
+			{
+				int max = allMembers.Max(m => m.AccessModifier.ToString().Length);
+				foreach (var m in allMembers)
+					m.AccessModifierLen = max;
+
+				max = allMembers.Max(m => m.CalcModifierLen());
+				foreach (var m in allMembers)
+					m.ModifierLen = max;
+
+				max = allMembers.Max(m => (m.BuildType() ?? "").Length);
+				foreach (var m in allMembers)
+					m.TypeLen = max;
+
+				var notHasGetter = allMembers.OfType<Property>().Any(m => m.IsAuto && !m.HasGetter);
+				var notHasSetter = allMembers.OfType<Property>().Any(m => m.IsAuto && !m.HasSetter);
+
+				foreach (var p in allMembers.OfType<Property>())
+				{
+					if (notHasGetter) p.GetterLen = 13;
+					if (notHasSetter) p.SetterLen = 13;
+				}
+
+				max = allMembers.Max(m => m.Name.Length);
+				foreach (var m in allMembers)
+					m.NameLen = max;
+
+				max = allMembers.Max(m => m.CalcParamLen());
+				foreach (var m in allMembers)
+					m.ParamLen = max;
+
+				max = allMembers.Max(m => m.CalcBodyLen());
+				foreach (var m in allMembers)
+					m.BodyLen = max;
+
+				var members =
+				(
+					from m in allMembers
+					select new
+					{
+						m,
+						attrs =
+						(
+							from a in m.Attributes
+							group a by a.Name into gr
+							select gr.Select((a,i) => new { a, name = a.Name + "." + i }).ToList() into s
+							from a in s
+							select a
+						).ToList()
+					}
+				).ToList();
+
+				var attrWeight =
+				(
+					from m in members
+					from a in m.attrs
+					group a by a.name into gr
+					select new { gr.Key, Count = gr.Count() }
+				).ToDictionary(a => a.Key, a => a.Count);
+
+				var q =
+					from m in members
+					where m.attrs.Count > 0
+					select new { m, w = m.attrs.Sum(aa => attrWeight[aa.name]) } into m
+					orderby m.w descending
+					select m.m;
+
+				var attrs = new List<string>();
+
+				foreach (var m in q)
+				{
+					var list = m.attrs.Select(a => a.name).ToList();
+
+					if (attrs.Count == 0)
+						attrs.AddRange(list);
+					else
+					{
+						for (var i = 0; i < list.Count; i++)
+						{
+							var nm = list[i];
+
+							if (!attrs.Contains(nm))
+							{
+								for (var j = i + 1; j < list.Count; j++)
+								{
+									var idx = attrs.IndexOf(list[j]);
+
+									if (idx >= 0)
+									{
+										attrs.Insert(idx, nm);
+										break;
+									}
+								}
+							}
+
+							if (!attrs.Contains(nm))
+								attrs.Add(nm);
+						}
+					}
+				}
+
+				var mms = members.Select(m =>
+				{
+					var arr = new Attribute[attrs.Count];
+
+					foreach (var a in m.attrs)
+						arr[attrs.IndexOf(a.name)] = a.a;
+
+					return new { m.m, attrs = arr.ToList() };
+				}).ToList();
+
+				var idxs = Enumerable.Range(0, attrs.Count).Select(_ => new List<int>()).ToList();
+
+				for (var i = 0; i < mms.Count; i++)
+					for (var j = 0; j < mms[i].attrs.Count; j++)
+						if (mms[i].attrs[j] != null)
+							idxs[j].Add(i);
+
+				var toRemove = new List<int>();
+
+				for (int i = 1; i < idxs.Count; i++)
+				{
+					for (int j = 0; j < i; j++)
+					{
+						if (idxs[j] == null)
+							continue;
+
+						if (idxs[i].Intersect(idxs[j]).Count() == 0)
+						{
+							foreach (var m in mms)
+							{
+								if (m.attrs[i] != null)
+								{
+									m.attrs[j] = m.attrs[i];
+									m.attrs[i] = null;
+								}
+							}
+
+							idxs[j].AddRange(idxs[i]);
+							idxs[i] = null;
+							toRemove.Add(i);
+							break;
+						}
+					}
+
+				}
+
+				foreach (var n in toRemove.OrderByDescending(i => i))
+					foreach (var m in mms)
+						m.attrs.RemoveAt(n);
+
+				var lens = new int[attrs.Count - toRemove.Count];
+
+				foreach (var m in mms)
+				{
+					for (var i = 0; i < m.attrs.Count; i++)
+					{
+						var a = m.attrs[i];
+
+						if (a != null)
+						{
+							var len = a.Name.Length;
+
+							if (a.Parameters.Count >= 0)
+								len += a.Parameters.Sum(p => 2 + p.Length);
+
+							lens[i] = Math.Max(lens[i], len);
+						}
+					}
+				}
+
+				foreach (var m in allMembers)
+				{
+					if (!(m is MemberGroup))
+						m.BeginConditional(tt, IsCompact);
+
+					foreach (var c in m.Comment)
+						WriteComment(tt, c);
+
+					if (attrs.Count > 0)
+					{
+						var ma = mms.First(mr => mr.m == m);
+
+						if (m.Attributes.Count > 0)
+						{
+							tt.Write("[");
+
+							for (var i = 0; i < ma.attrs.Count; i++)
+							{
+								var a = ma.attrs[i];
+
+								if (a == null)
+								{
+									tt.WriteSpaces(lens[i]);
+									if (i + 1 < ma.attrs.Count)
+										tt.Write("  ");
+								}
+								else
+								{
+									var len = tt.GenerationEnvironment.Length;
+									a.Render(tt);
+									len = (tt.GenerationEnvironment.Length - len);
+
+									var commaAdded = false;
+
+									for (var j = i + 1; j < ma.attrs.Count; j++)
+									{
+										if (ma.attrs[j] != null)
+										{
+											SkipSpacesAndInsert(tt, ", ");
+											commaAdded = true;
+											break;
+										}
+									}
+
+									if (i + 1 < ma.attrs.Count && !commaAdded)
+										tt.Write("  ");
+
+									tt.WriteSpaces(lens[i] - len);
+								}
+							}
+
+							tt.Write("] ");
+						}
+						else
+						{
+							tt.WriteSpaces(lens.Sum() + ma.attrs.Count * 2 + 1);
+						}
+					}
+
+					m.Render(tt, true);
+
+					if (!IsCompact)
+						tt.WriteLine("");
+
+					if (!(m is MemberGroup))
+						m.EndConditional(tt, IsCompact);
+				}
+			}
+		}
+		else
+		{
+			foreach (var cm in Members)
+			{
+				if (cm is MemberBase)
+				{
+					var m = (MemberBase)cm;
+
+					if (!(m is MemberGroup))
+						m.BeginConditional(tt, IsCompact);
+
+					foreach (var c in m.Comment)
+						WriteComment(tt, c);
+
+					if (m.Attributes.Count > 0)
+					{
+						var q =
+							from a in m.Attributes
+							group a by a.Conditional ?? "";
+
+						foreach (var g in q)
+						{
+							if (g.Key.Length > 0)
+							{
+								tt.RemoveSpace();
+								tt.WriteLine("#if " + g.Key);
+							}
+
+							var attrs = g.ToList();
+
+							var aa = attrs.Where(a => !a.IsSeparated).ToList();
+
+							if (aa.Count > 0)
+							{
+								tt.Write("[");
+
+								for (var i = 0; i < aa.Count; i++)
+								{
+									if (i > 0) tt.Write(", ");
+									aa[i].Render(tt);
+								}
+
+								tt.WriteLine("]");
+							}
+
+							aa = attrs.Where(a => a.IsSeparated).ToList();
+
+							foreach (var a in aa)
+							{
+								tt.Write("[");
+								a.Render(tt);
+								tt.WriteLine("]");
+							}
+
+							if (g.Key.Length > 0)
+							{
+								tt.RemoveSpace();
+								tt.WriteLine("#endif");
+							}
+						}
+					}
+
+					m.Render(tt, false);
+
+					if (m.InsertBlankLineAfter)
+						tt.WriteLine("");
+
+					if (!(m is MemberGroup))
+						m.EndConditional(tt, IsCompact);
+				}
+				else if (cm is TypeBase)
+				{
+					var t = (TypeBase)cm;
+
+					t.Render(tt);
+					tt.WriteLine("");
+				}
+			}
+		}
+
+		tt.Trim();
+
+		EndConditional(tt, isCompact);
+
+		if (!string.IsNullOrEmpty(Region))
+		{
+			tt.WriteLine("");
+			EndRegion(tt);
+		}
+	}
+
+	public override IEnumerable<ITree> GetNodes() { return Members; }
+
+	public override void SetTree()
+	{
+		foreach (var ch in GetNodes())
+		{
+			ch.Parent = this;
+			ch.SetTree();
+		}
+	}
+}
+
+static Action<GeneratedTextTransformation,Field> WriteField = (tt,f) =>
+{
+	var am = f.AccessModifier.ToString().ToLower();
+	var mdf =
+		(f.IsStatic   ? " static"   : "") +
+		(f.IsReadonly ? " readonly" : "") ;
+
+	tt.Write("{0}{1}{2}{3} {4}{5} {6}",
+		am,            LenDiff(f.AccessModifierLen, am),
+		mdf,           LenDiff(f.ModifierLen,       mdf),
+		f.BuildType(), LenDiff(f.TypeLen,           f.BuildType()),
+		f.Name);
+
+	if (f.InitValue != null)
+	{
+		tt.Write(" = {0}", f.InitValue);
+	}
+
+	tt.Write(";");
+
+	if (!string.IsNullOrEmpty(f.EndLineComment))
+	{
+		tt.WriteSpaces(f.NameLen - f.Name.Length + f.BodyLen + f.ParamLen - 1);
+		tt.Write(" ");
+		WriteComment(tt, " " + f.EndLineComment);
+	}
+	else
+		tt.WriteLine("");
+};
+
+public partial class Field : MemberBase
+{
+	public bool   IsStatic;
+	public bool   IsReadonly;
+	public string InitValue;
+
+	public Field()
+	{
+	}
+
+	public Field(Func<string> typeBuilder, string name)
+	{
+		TypeBuilder = typeBuilder;
+		Name = name;
+	}
+
+	public override int CalcModifierLen()
+	{
+		return
+			(IsStatic   ? " static".  Length : 0) +
+			(IsReadonly ? " readonly".Length : 0) ;
+	}
+
+	public override int  CalcBodyLen() { return InitValue == null ? 1 : 4 + InitValue.Length; }
+
+	public override void Render(GeneratedTextTransformation tt, bool isCompact)
+	{
+		WriteField(tt, this);
+	}
+}
+
+static Action<GeneratedTextTransformation,Event> WriteEvent = (tt,m) =>
+{
+	var am  = m.AccessModifier.ToString().ToLower();
+	var mdf =
+		(m.IsStatic  ? " static"  : "") +
+		(m.IsVirtual ? " virtual" : "") +
+		" event";
+
+	tt.Write("{0}{1}{2}{3} {4}{5} {6};",
+		am,            LenDiff(m.AccessModifierLen, am),
+		mdf,           LenDiff(m.ModifierLen,       mdf),
+		m.BuildType(), LenDiff(m.TypeLen,           m.BuildType()),
+		m.Name);
+
+	if (!string.IsNullOrEmpty(m.EndLineComment))
+	{
+		tt.WriteSpaces(m.NameLen - m.Name.Length + m.BodyLen + m.ParamLen - 1);
+		tt.Write(" ");
+		WriteComment(tt, " " + m.EndLineComment);
+	}
+	else
+		tt.WriteLine("");
+};
+
+public partial class Event : MemberBase
+{
+	public bool IsStatic;
+	public bool IsVirtual;
+
+	public Event()
+	{
+	}
+
+	public Event(Func<string> typeBuilder, string name)
+	{
+		TypeBuilder = typeBuilder;
+		Name = name;
+	}
+
+	public override int CalcModifierLen()
+	{
+		return
+			(IsStatic  ? " static". Length : 0) +
+			(IsVirtual ? " virtual".Length : 0) +
+			" event".Length;
+	}
+
+	public override int CalcBodyLen() { return 1; }
+
+	public override void Render(GeneratedTextTransformation tt, bool isCompact)
+	{
+		WriteEvent(tt, this);
+	}
+}
+
+static Action<GeneratedTextTransformation,Property,bool> WriteProperty = (tt,p,compact) =>
+{
+	var am  = p.AccessModifier.ToString().ToLower();
+//	var mdf = p.IsVirtual ? " virtual" : "";
+	var mdf = p.IsAbstract ? " abstract" : p.IsVirtual ? " virtual" : p.IsOverride ? " override" : p.IsStatic ? " static" : "";
+
+	tt.Write("{0}{1}{2}{3} {4}{5} {6}",
+		am,            LenDiff(p.AccessModifierLen, am),
+		mdf,           LenDiff(p.ModifierLen,       mdf),
+		p.BuildType(), LenDiff(p.TypeLen,           p.BuildType()),
+		p.Name);
+
+	Action writeComment = () =>
+	{
+		if (!string.IsNullOrEmpty(p.EndLineComment))
+		{
+			tt.Write(" ");
+			WriteComment(tt, " " + p.EndLineComment);
+		}
+		else
+			tt.WriteLine("");
+	};
+
+	if (p.IsAuto)
+	{
+		tt.Write(LenDiff(p.NameLen + p.ParamLen, p.Name));
+
+		var len = tt.GenerationEnvironment.Length;
+
+		tt.Write(" { ");
+
+		if (!p.HasGetter)
+			tt.Write("private ");
+		else if (p.GetterLen == 13)
+			tt.Write("        ");
+		tt.Write("get; ");
+
+		if (!p.HasSetter)
+			tt.Write("private ");
+		else if (p.SetterLen == 13)
+			tt.Write("        ");
+		tt.Write("set; ");
+
+		tt.Write("}");
+
+		if (!string.IsNullOrEmpty(p.EndLineComment))
+			tt.WriteSpaces(p.BodyLen - (tt.GenerationEnvironment.Length - len));
+		writeComment();
+	}
+	else
+	{
+		if (compact)
+		{
+			tt.Write(LenDiff(p.NameLen + p.ParamLen, p.Name));
+
+			var len = tt.GenerationEnvironment.Length;
+
+			tt.Write(" { ");
+
+			if (p.HasGetter)
+			{
+				tt.Write("get { ");
+				foreach (var t in p.BuildGetBody())
+					tt.Write("{0} ", t);
+				tt.Write("} ");
+			}
+
+			if (p.HasSetter)
+			{
+				tt.Write("set { ");
+				foreach (var t in p.BuildSetBody())
+					tt.Write("{0} ", t);
+				tt.Write("} ");
+			}
+
+			tt.Write("}");
+
+			if (!string.IsNullOrEmpty(p.EndLineComment))
+				tt.WriteSpaces(p.BodyLen - (tt.GenerationEnvironment.Length - len));
+			writeComment();
+		}
+		else
+		{
+			writeComment();
+
+			tt.WriteLine("{");
+			tt.PushIndent("\t");
+
+			if (p.HasGetter)
+			{
+				var getBody = p.BuildGetBody().ToArray();
+				if (getBody.Length == 1)
+				{
+					tt.WriteLine("get {{ {0} }}", getBody[0]);
+				}
+				else
+				{
+					tt.WriteLine("get");
+					tt.WriteLine("{");
+					tt.PushIndent("\t");
+
+					foreach (var t in getBody)
+						tt.WriteLine(t);
+
+					tt.PopIndent();
+					tt.WriteLine("}");
+				}
+			}
+
+			if (p.HasSetter)
+			{
+				var setBody = p.BuildSetBody().ToArray();
+				if (setBody.Length == 1)
+				{
+					tt.WriteLine("set {{ {0} }}", setBody[0]);
+				}
+				else
+				{
+					tt.WriteLine("set");
+					tt.WriteLine("{");
+					tt.PushIndent("\t");
+
+					foreach (var t in setBody)
+						tt.WriteLine(t);
+
+					tt.PopIndent();
+					tt.WriteLine("}");
+				}
+			}
+
+			tt.PopIndent();
+			tt.WriteLine("}");
+		}
+	}
+};
+
+public partial class Property : MemberBase
+{
+	public bool         IsAuto    = true;
+	public string       InitValue;
+	public bool         IsVirtual;
+	public bool         IsOverride;
+	public bool         IsAbstract;
+	public bool         IsStatic;
+	public bool         HasGetter = true;
+	public bool         HasSetter = true;
+	public List<Func<IEnumerable<string>>> GetBodyBuilders = new List<Func<IEnumerable<string>>>();
+	public List<Func<IEnumerable<string>>> SetBodyBuilders = new List<Func<IEnumerable<string>>>();
+
+	public int GetterLen = 5;
+	public int SetterLen = 5;
+
+	public Property()
+	{
+	}
+
+	public Property(Func<string> typeBuilder, string name, Func<IEnumerable<string>> getBodyBuilder = null, Func<IEnumerable<string>> setBodyBuilder = null)
+	{
+		TypeBuilder = typeBuilder;
+		Name = name;
+
+		InitBody(getBodyBuilder, setBodyBuilder);
+	}
+
+	public override int CalcModifierLen()
+	{
+		return IsVirtual ? " virtual".Length : 0;
+	}
+
+	public override int CalcBodyLen()
+	{
+		if (IsAuto)
+			return 4 + GetterLen + SetterLen; // ' { get; set; }'
+
+		var len = " {".Length;
+
+		if (HasGetter)
+		{
+			len += " get {".Length;
+			foreach (var t in BuildGetBody())
+				len += 1 + t.Length;
+			len += " }".Length;
+		}
+
+		if (HasSetter)
+		{
+			len += " set {".Length;
+			foreach (var t in BuildSetBody())
+				len += 1 + t.Length;
+			len += " }".Length;
+		}
+
+		len += " }".Length;
+
+		return len;
+	}
+
+	public override void Render(GeneratedTextTransformation tt, bool isCompact)
+	{
+		if (!IsAuto && HasGetter)
+		{
+			var getBody = BuildGetBody().ToArray();
+			if (getBody.Length == 1)
+			{
+				var t = getBody[0];
+
+				if (!t.StartsWith("return"))
+				{
+					t = "return " + t;
+
+					if (!t.EndsWith(";"))
+						t += ";";
+
+					GetBodyBuilders.Clear();
+					GetBodyBuilders.Add(() => new [] { t });
+				}
+			}
+		}
+
+		WriteProperty(tt, this, isCompact);
+	}
+
+	public Property InitBody(Func<IEnumerable<string>> getBodyBuilder = null, Func<IEnumerable<string>> setBodyBuilder = null)
+	{
+		IsAuto = getBodyBuilder == null && setBodyBuilder == null;
+
+		if (getBodyBuilder != null) GetBodyBuilders.Add(getBodyBuilder);
+		if (setBodyBuilder != null) SetBodyBuilders.Add(setBodyBuilder);
+
+		if (!IsAuto)
+		{
+			HasGetter = getBodyBuilder != null;
+			HasSetter = setBodyBuilder != null;
+		}
+
+		return this;
+	}
+
+	public Property InitGetter(Func<IEnumerable<string>> getBodyBuilder)
+	{
+		return InitBody(getBodyBuilder, null);
+	}
+
+	public IEnumerable<string> BuildGetBody()
+	{
+		return GetBodyBuilders.SelectMany(builder => builder?.Invoke() ?? Array.Empty<string>());
+	}
+
+	public IEnumerable<string> BuildSetBody()
+	{
+		return SetBodyBuilders.SelectMany(builder => builder?.Invoke() ?? Array.Empty<string>());
+	}
+}
+
+static Action<GeneratedTextTransformation,Method,bool> WriteMethod = (tt,m,compact) =>
+{
+	var am1  = m.AccessModifier.ToString().ToLower();
+	var len1 = m.AccessModifierLen;
+	var am2  = "";
+	var len2 = 0;
+	var mdf  = m.IsAbstract ? " abstract" : m.IsVirtual ? " virtual" : m.IsOverride ? " override" : m.IsStatic ? " static" : "";
+	var mlen = m.ModifierLen;
+
+	if (am1 == "partial" && mdf.Length > 0)
+	{
+		am2 = " " + am1; len2 = len1 + 1;
+		am1 = "";        len1 = 0;
+		mdf = mdf.Trim();
+		mlen--;
+	}
+
+	tt.Write("{0}{1}{2}{3}{4}{5}{6}{7}{8} {9}{10}",
+		am1,           LenDiff(len1, am1),
+		mdf,           LenDiff(mlen, mdf),
+		am2,           LenDiff(len2, am2),
+		m.BuildType() == null ? "" : " ",
+		m.BuildType(), LenDiff(m.TypeLen,     m.BuildType() ?? ""),
+		m.Name,
+		m.GenericArguments.Count > 0 ? $"<{string.Join(", ", m.GenericArguments)}>" : string.Empty);
+
+	Action writeComment = () =>
+	{
+		if (!string.IsNullOrEmpty(m.EndLineComment))
+		{
+			tt.Write(" ");
+			WriteComment(tt, " " + m.EndLineComment);
+		}
+		else
+			tt.WriteLine("");
+	};
+
+	Action writeParams = () =>
+	{
+		tt.Write("(");
+
+		for (int i = 0; i < m.ParameterBuilders.Count; i++)
+		{
+			if (i > 0)
+				tt.Write(", ");
+			tt.Write(m.ParameterBuilders[i]());
+		}
+
+		tt.Write(")");
+	};
+
+	if (compact)
+	{
+		tt.Write(LenDiff(m.NameLen, m.Name));
+
+		var len = tt.GenerationEnvironment.Length;
+
+		writeParams();
+
+		foreach (var s in m.AfterSignature)
+		{
+			tt.Write(" ");
+			tt.Write(s);
+		}
+
+		len = tt.GenerationEnvironment.Length - len;
+
+		if (m.IsAbstract || m.AccessModifier == AccessModifier.Partial)
+		{
+			tt.Write(";");
+			len = 0;
+		}
+		else
+		{
+			tt.WriteSpaces(m.ParamLen - len);
+
+			len = tt.GenerationEnvironment.Length;
+
+			tt.Write(" {");
+
+			foreach (var t in m.BuildBody())
+				tt.Write(" {0}", t);
+
+			tt.Write(" }");
+		}
+
+		if (!string.IsNullOrEmpty(m.EndLineComment))
+			tt.WriteSpaces(m.BodyLen - (tt.GenerationEnvironment.Length - len));
+		writeComment();
+	}
+	else
+	{
+		writeParams ();
+		writeComment();
+
+		tt.PushIndent("\t");
+		foreach (var s in m.AfterSignature)
+			tt.WriteLine(s);
+		tt.PopIndent();
+
+		tt.WriteLine("{");
+		tt.PushIndent("\t");
+
+		foreach (var t in m.BuildBody())
+		{
+			if (t.Length > 1 && t[0] == '#')
+			{
+				tt.RemoveSpace();
+			}
+
+			tt.WriteLine(t);
+		}
+
+		tt.PopIndent();
+		tt.WriteLine("}");
+	}
+};
+
+public partial class Method : MemberBase
+{
+	public bool         IsAbstract;
+	public bool         IsVirtual;
+	public bool         IsOverride;
+	public bool         IsStatic;
+	public List<string> GenericArguments        = new List<string>();
+	public List<string> AfterSignature          = new List<string>();
+	public List<Func<string>> ParameterBuilders = new List<Func<string>>();
+	public List<Func<IEnumerable<string>>> BodyBuilders = new List<Func<IEnumerable<string>>>();
+
+	public Method()
+	{
+	}
+
+	public Method(Func<string> typeBuilder, string name, IEnumerable<Func<string>> parameterBuilders = null, params Func<IEnumerable<string>>[] bodyBuilders)
+	{
+		TypeBuilder = typeBuilder;
+		Name = name;
+
+		if (parameterBuilders  != null) ParameterBuilders.AddRange(parameterBuilders);
+		if (bodyBuilders       != null) BodyBuilders.AddRange(bodyBuilders);
+	}
+
+	public static Method Create(string type, string name, IEnumerable<string> parameters = null, IEnumerable<string> body = null)
+	{
+		return new Method(
+			() => type,
+			name,
+			parameters?.Select<string,Func<string>>((string p) => () => p),
+			body?.Select<string,Func<IEnumerable<string>>>(p => () => new[] { p }).ToArray());
+	}
+
+	public IEnumerable<string> BuildBody()
+	{
+		return BodyBuilders.SelectMany(builder => builder?.Invoke() ?? Array.Empty<string>());
+	}
+
+	public override int CalcModifierLen()
+	{
+		return
+			IsAbstract ? " abstract".Length :
+			IsVirtual  ? " virtual".Length  :
+			IsStatic   ? " static".Length   : 0;
+	}
+
+	public override int CalcBodyLen()
+	{
+		if (IsAbstract || AccessModifier == AccessModifier.Partial)
+			return 1;
+
+		var len = " {".Length;
+
+		foreach (var t in BuildBody())
+			len += 1 + t.Length;
+
+		len += " }".Length;
+
+		return len;
+	}
+
+	public override int CalcParamLen()
+	{
+		return ParameterBuilders.Sum(p => p().Length + 2);
+	}
+
+	public override void Render(GeneratedTextTransformation tt, bool isCompact)
+	{
+		WriteMethod(tt, this, isCompact);
+	}
+}
+
+static Action<GeneratedTextTransformation,Attribute> WriteAttribute = (tt,a) =>
+{
+	tt.Write(a.Name);
+
+	if (a.Parameters.Count > 0)
+	{
+		tt.Write("(");
+
+		for (var i = 0; i < a.Parameters.Count; i++)
+		{
+			if (i > 0)
+				if (a.Parameters[i - 1].All(c => c == ' '))
+					tt.Write("  ");
+				else
+					SkipSpacesAndInsert(tt, ", ");
+			tt.Write(a.Parameters[i]);
+		}
+
+		SkipSpacesAndInsert(tt, ")");
+	}
+};
+
+public partial class Attribute
+{
+	public string       Name;
+	public List<string> Parameters = new List<string>();
+	public string       Conditional;
+	public bool         IsSeparated;
+
+	public Attribute()
+	{
+	}
+
+	public Attribute(string name, params string[] ps)
+	{
+		Name = name;
+		Parameters.AddRange(ps);
+	}
+
+	public virtual void Render(GeneratedTextTransformation tt)
+	{
+		WriteAttribute(tt, this);
+	}
+}
+
+// Helpers.
+//
+
+Func<string,string> ToPlural   = s => s + "s";
+Func<string,string> ToSingular = s => s;
+
+static string LenDiff(int max, string str)
+{
+	var s = "";
+
+	while (max-- > str.Length)
+		s += " ";
+
+	return s;
+}
+
+public void WriteSpaces(int len)
+{
+	while (len-- > 0)
+		Write(" ");
+}
+
+void RemoveSpace()
+{
+	Write(" ");
+
+	while (GenerationEnvironment.Length > 0 &&
+		(GenerationEnvironment[GenerationEnvironment.Length - 1] == ' ' ||
+		 GenerationEnvironment[GenerationEnvironment.Length - 1] == '\t'))
+		GenerationEnvironment.Length--;
+}
+
+public static IEnumerable<ITree> GetTreeNodes(ITree parent)
+{
+	foreach (var node in parent.GetNodes())
+	{
+		yield return node;
+
+		foreach (var grandNode in GetTreeNodes(node))
+			yield return grandNode;
+	}
+}
+
+public static ITree FindNode(ITree parent, Func<ITree,bool> func)
+{
+	foreach (var node in parent.GetNodes())
+	{
+		if (func(node))
+			return node;
+
+		var n = FindNode(node, func);
+
+		if (n != null)
+			return n;
+	}
+
+	return null;
+}
+
+static void SkipSpacesAndInsert(GeneratedTextTransformation tt, string value)
+{
+	var l = tt.GenerationEnvironment.Length;
+
+	for (; l > 0 && tt.GenerationEnvironment[l - 1] == ' '; l--)
+	{
+	}
+
+	tt.GenerationEnvironment.Insert(l, value);
+}
+
+
+string ToCamelCase(string name)
+{
+	var n = 0;
+
+	foreach (var c in name)
+	{
+		if (char.IsUpper(c))
+			n++;
+		else
+			break;
+	}
+
+	if (n == 0)
+		return name;
+
+	if (n == name.Length)
+		return name.ToLower();
+
+	n = Math.Max(1, n - 1);
+
+	return name.Substring(0, n).ToLower() + name.Substring(n);
+}
+
+event Action<Property,string,object> SetPropertyValueAction;
+
+void SetPropertyValue(Property propertyObject, string propertyName, object value)
+{
+	if (SetPropertyValueAction != null)
+		SetPropertyValueAction(propertyObject, propertyName, value);
+}
+
+static string ToStringLiteral(string value)
+{
+	if (value == null)
+		return "null";
+
+	var sb = new StringBuilder("\"");
+
+	foreach (var chr in value)
+	{
+		switch (chr)
+		{
+			case '\t':     sb.Append("\\t");            break;
+			case '\n':     sb.Append("\\n");            break;
+			case '\r':     sb.Append("\\r");            break;
+			case '\\':     sb.Append("\\\\");           break;
+			case '"' :     sb.Append("\\\"");           break;
+			case '\0':     sb.Append("\\0");            break;
+			case '\u0085':
+			case '\u2028':
+			case '\u2029':
+					 sb.Append($"\\u{(ushort)chr:X4}"); break;
+			default: sb.Append(chr);                    break;
+		}
+	}
+
+	sb.Append('"');
+
+	return sb.ToString();
+}
+
+#>
diff --git a/src/Version/LinqToDB.Templates/Validation.ttinclude b/src/Version/LinqToDB.Templates/Validation.ttinclude
new file mode 100644
index 0000000000000000000000000000000000000000..45a7e84399626f034eb6674ddff2808f2d83a61c
--- /dev/null
+++ b/src/Version/LinqToDB.Templates/Validation.ttinclude
@@ -0,0 +1,189 @@
+<#
+	{
+		var beforeGenerateModel = BeforeGenerateModel;
+		BeforeGenerateModel = () =>
+		{
+			beforeGenerateModel();
+			ValidationImpl();
+		};
+	}
+#>
+<#+
+void ValidationImpl()
+{
+	foreach (Class cl in GetTreeNodes(Model).OfType<Class>())
+	{
+		var validationGroup = new MemberGroup
+		{
+			Region = "Validation",
+		};
+
+		var props = GetTreeNodes(cl).OfType<Property>().Where(p => p.CustomValidation).ToList();
+
+		if (props.Count > 0)
+		{
+			if (!Model.Usings.Contains("System.Collections.Generic"))
+				Model.Usings.Add("System.Collections.Generic");
+
+			var isValid      = new Method(() => "bool", "IsValid", new Func<string>[] { () => cl.Name + " obj" }) { IsStatic = true };
+			var validator    = new Class("CustomValidator", isValid) { IsStatic = true, };
+			var partialGroup = new MemberGroup { IsCompact = true };
+
+			validationGroup.Members.Add(new Field(() => "int", "_isValidCounter") { Attributes = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } } });
+			validationGroup.Members.Add(validator);
+			validationGroup.Members.Add(partialGroup);
+
+			isValid.BodyBuilders.Add(() => new []
+			{
+				"try",
+				"{",
+				"\tobj._isValidCounter++;",
+				""
+			});
+
+			var ret = "\treturn ";
+
+			for (var idx = 0; idx < props.Count; idx++)
+			{
+				var i = idx;
+				var p = props[i];
+
+				var name  = p.Name.Trim();
+				var mname = "Validate" + name;
+
+				cl.Attributes.Add(
+					new Attribute("CustomValidation",
+						"typeof(" + cl.Name + ".CustomValidator)",
+						ToStringLiteral(mname))
+						{
+							IsSeparated = true
+						});
+
+				isValid.BodyBuilders.Add(() => new [] {
+					"\tvar flag" + i + " = ValidationResult.Success == " + mname + "(obj, obj." + name + ");" });
+
+				ret += (i == 0 ? "" : " || ") + "flag" + i;
+
+				var validate = new Method(() => "ValidationResult", mname,
+					new Func<string>[] { () => cl.Name + " obj", () => p.BuildType().Trim() + " value" }) { IsStatic = true };
+
+				validate.BodyBuilders.Add(() => new []
+				{
+					"var list = new List<ValidationResult>();",
+					"",
+					"Validator.TryValidateProperty(",
+					"\tvalue,",
+					"\tnew ValidationContext(obj, null, null) { MemberName = NameOf" + name + " }, list);",
+					"",
+					"obj." + mname + "(value, list);",
+					"",
+					"if (list.Count > 0)",
+					"{",
+					"\tforeach (var result in list)",
+					"\t\tforeach (var name in result.MemberNames)",
+					"\t\t\tobj.AddError(name, result.ErrorMessage);",
+					"",
+					"\treturn list[0];",
+					"}",
+					"",
+					"obj.RemoveError(NameOf" + name + ");",
+					"",
+					"return ValidationResult.Success;"
+				});
+
+				validator.Members.Add(validate);
+
+				partialGroup.Members.Add(new Method(
+					() => "void",
+					mname,
+					new Func<string>[]
+					{
+						() => p.BuildType().Trim() + " value",
+						() => "List<ValidationResult> validationResults",
+					})
+					{
+						AccessModifier = AccessModifier.Partial,
+					});
+			}
+
+			isValid.BodyBuilders.Add(() => new []
+			{
+				"",
+				ret + ";",
+				"}",
+				"finally",
+				"{",
+				"\tobj._isValidCounter--;",
+				"}"
+			});
+		}
+
+		props = GetTreeNodes(cl).OfType<Property>().Where(p => p.ValidateProperty && p.HasSetter).ToList();
+
+		if (props.Count > 0)
+		{
+			foreach (var p in props)
+			{
+				var setBody = p.BuildSetBody().ToList();
+				if (setBody.Count > 0)
+					setBody.Insert(0, "");
+
+				setBody.Insert(0, "if (_validationLockCounter == 0)");
+				setBody.Insert(1, "{");
+
+				if (p.CustomValidation)
+				{
+					setBody.Insert(2, "\tvar validationResult = CustomValidator.Validate" + p.Name.Trim() + "(this, value);");
+					setBody.Insert(3, "\tif (validationResult != ValidationResult.Success)");
+					setBody.Insert(4, "\t\tthrow new ValidationException(validationResult, null, null);");
+					setBody.Insert(5, "}");
+				}
+				else
+				{
+					setBody.Insert(2, "\tValidator.ValidateProperty(");
+					setBody.Insert(3, "\t\tvalue,");
+					setBody.Insert(4, string.Format("\t\tnew ValidationContext(this, null, null) {{ MemberName = NameOf{0} }});", p.Name.Trim()));
+					setBody.Insert(5, "}");
+				}
+
+				p.SetBodyBuilders.Clear();
+				p.SetBodyBuilders.Add(() => setBody.ToArray());
+			}
+
+			validationGroup.Members.Add(new Field(() => "int", "_validationLockCounter")
+			{
+				AccessModifier = AccessModifier.Private,
+				InitValue      = "0",
+				Attributes     = { new Attribute("field : NonSerialized") { Conditional = "!SILVERLIGHT" } }
+			});
+
+			validationGroup.Members.Add(new Method (() => "void", "LockValidation",   null, () => new[] { "_validationLockCounter++;" }));
+			validationGroup.Members.Add(new Method (() => "void", "UnlockValidation", null, () => new[] { "_validationLockCounter--;" }));
+		}
+
+		if (validationGroup.Members.Count > 0)
+		{
+			if (!Model.Usings.Contains("System.ComponentModel.DataAnnotations"))
+				Model.Usings.Add("System.ComponentModel.DataAnnotations");
+
+			cl.Members.Add(validationGroup);
+			cl.SetTree();
+		}
+	}
+}
+
+partial class Property
+{
+	public bool CustomValidation;
+	public bool ValidateProperty;
+
+	public bool Validate
+	{
+		set
+		{
+			CustomValidation = value;
+			ValidateProperty = value;
+		}
+	}
+}
+#>
diff --git a/src/Version/NLog.config b/src/Version/NLog.config
new file mode 100644
index 0000000000000000000000000000000000000000..7a0f3aa130d54048b05fae55068b588eafed2eac
--- /dev/null
+++ b/src/Version/NLog.config
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
+      autoReload="true"
+      throwExceptions="false"
+      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
+
+  <!-- optional, add some variables
+  https://github.com/nlog/NLog/wiki/Configuration-file#variables
+  -->
+  <variable name="myvar" value="myvalue"/>
+
+  <!--
+  See https://github.com/nlog/nlog/wiki/Configuration-file
+  for information on customizing logging rules and outputs.
+   -->
+  <targets>
+
+    <!--
+    add your targets here
+    See https://github.com/nlog/NLog/wiki/Targets for possible targets.
+    See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
+    -->
+
+    <!--
+    Write events to a file with the date in the filename.
+    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
+            layout="${longdate} ${uppercase:${level}} ${message}" />
+    -->
+  </targets>
+
+  <rules>
+    <!-- add your logging rules here -->
+
+    <!--
+    Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
+    <logger name="*" minlevel="Debug" writeTo="f" />
+    -->
+  </rules>
+</nlog>
diff --git a/src/Version/NLog.xsd b/src/Version/NLog.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..16d888c8a12847595252b8cd0a4a220397b9584f
--- /dev/null
+++ b/src/Version/NLog.xsd
@@ -0,0 +1,3556 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema id="NLog" targetNamespace="http://www.nlog-project.org/schemas/NLog.xsd" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
+  <xs:element name="nlog" type="NLogConfiguration" />
+  <xs:complexType name="NLogConfiguration">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="extensions" type="NLogExtensions" />
+      <xs:element name="include" type="NLogInclude" />
+      <xs:element name="variable" type="NLogVariable" />
+      <xs:element name="targets" type="NLogTargets" />
+      <xs:element name="rules" type="NLogRules" />
+      <xs:element name="time" type="TimeSource" />
+    </xs:choice>
+    <xs:attribute name="autoReload" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Watch config file for changes and reload automatically.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogToConsole" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Print internal NLog messages to the console. Default value is: false</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogToConsoleError" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Print internal NLog messages to the console error output. Default value is: false</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogFile" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Write internal NLog messages to the specified file.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogLevel" type="NLogLevel">
+      <xs:annotation>
+        <xs:documentation>Log level threshold for internal log messages. Default value is: Info.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="globalThreshold" type="NLogLevel">
+      <xs:annotation>
+        <xs:documentation>Global log level threshold for application log messages. Messages below this level won't be logged.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="throwExceptions" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Throw an exception when there is an internal error. Default value is: false. Not recommend to set to true in production!</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="throwConfigExceptions" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Throw an exception when there is a configuration error. If not set, determined by throwExceptions.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="keepVariablesOnReload" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogToTrace" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="internalLogIncludeTimestamp" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Write timestamps for internal NLog messages. Default value is: true.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="useInvariantCulture" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Use InvariantCulture as default culture instead of CurrentCulture.  Default value is: false.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="parseMessageTemplates" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Perform message template parsing and formatting of LogEvent messages (true = Always, false = Never, empty = Auto Detect). Default value is: empty.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLogTargets">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="default-wrapper" type="WrapperTargetBase" />
+      <xs:element name="default-target-parameters" type="Target" />
+      <xs:element name="target" type="Target" />
+      <xs:element name="wrapper-target" type="WrapperTargetBase" />
+      <xs:element name="compound-target" type="CompoundTargetBase" />
+    </xs:choice>
+    <xs:attribute name="async" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes).</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLogRules">
+    <xs:sequence minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="logger" type="NLogLoggerRule" />
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="NLogExtensions">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="add" type="NLogExtensionsAdd" />
+    </xs:choice>
+  </xs:complexType>
+  <xs:complexType name="NLogExtensionsAdd">
+    <xs:attribute name="prefix" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Prefix for targets/layout renderers/filters/conditions loaded from this assembly.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="assemblyFile" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Load NLog extensions from the specified file (*.dll)</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="assembly" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Load NLog extensions from the specified assembly. Assembly name should be fully qualified.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLogLoggerRule">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="filters" type="NLogFilters" />
+    </xs:choice>
+    <xs:attribute name="name" use="optional">
+      <xs:annotation>
+        <xs:documentation>Name of the logger. May include  wildcard characters ('*' or '?').</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="levels" type="NLogLevelList">
+      <xs:annotation>
+        <xs:documentation>Comma separated list of levels that this rule matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="minlevel" type="NLogLevel">
+      <xs:annotation>
+        <xs:documentation>Minimum level that this rule matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="maxlevel" type="NLogLevel">
+      <xs:annotation>
+        <xs:documentation>Maximum level that this rule matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="level" type="NLogLevel">
+      <xs:annotation>
+        <xs:documentation>Level that this rule matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="writeTo" type="NLogTargetIDList">
+      <xs:annotation>
+        <xs:documentation>Comma separated list of target names.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="final" type="xs:boolean" default="false">
+      <xs:annotation>
+        <xs:documentation>Ignore further rules if this one matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="ruleName" type="xs:string" use="optional">
+      <xs:annotation>
+        <xs:documentation>Rule identifier to allow rule lookup with Configuration.FindRuleByName and Configuration.RemoveRuleByName.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLogFilters">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="when" type="when" />
+      <xs:element name="whenContains" type="whenContains" />
+      <xs:element name="whenEqual" type="whenEqual" />
+      <xs:element name="whenNotContains" type="whenNotContains" />
+      <xs:element name="whenNotEqual" type="whenNotEqual" />
+      <xs:element name="whenRepeated" type="whenRepeated" />
+    </xs:choice>
+    <xs:attribute name="defaultAction" type="FilterResult">
+      <xs:annotation>
+        <xs:documentation>Default action if none of the filters match.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:simpleType name="NLogLevel">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Off" />
+      <xs:enumeration value="Trace" />
+      <xs:enumeration value="Debug" />
+      <xs:enumeration value="Info" />
+      <xs:enumeration value="Warn" />
+      <xs:enumeration value="Error" />
+      <xs:enumeration value="Fatal" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="LineEndingMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Default" />
+      <xs:enumeration value="CRLF" />
+      <xs:enumeration value="CR" />
+      <xs:enumeration value="LF" />
+      <xs:enumeration value="None" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLogLevelList">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="(|Trace|Debug|Info|Warn|Error|Fatal)(,(Trace|Debug|Info|Warn|Error|Fatal))*" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="NLogInclude">
+    <xs:attribute name="file" type="SimpleLayoutAttribute" use="required">
+      <xs:annotation>
+        <xs:documentation>Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="ignoreErrors" type="xs:boolean" use="optional" default="false">
+      <xs:annotation>
+        <xs:documentation>Ignore any errors in the include file.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLogVariable">
+    <xs:choice minOccurs="0" maxOccurs="1">
+      <xs:element name="value" minOccurs="0" maxOccurs="1" type="xs:string">
+        <xs:annotation>
+          <xs:documentation>Variable value. Note, the 'value' attribute has precedence over this one.</xs:documentation>
+        </xs:annotation>
+      </xs:element>
+    </xs:choice>
+    <xs:attribute name="name" type="xs:string" use="required">
+      <xs:annotation>
+        <xs:documentation>Variable name.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="value" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Variable value.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:simpleType name="NLogTargetIDList">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="(|([a-zA-Z][a-zA-Z0-9_\-]*))(,([a-zA-Z][a-zA-Z0-9_\-]*))*" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="Target" abstract="true"></xs:complexType>
+  <xs:complexType name="TargetRef">
+    <xs:attribute name="name" type="xs:string" use="required" />
+  </xs:complexType>
+  <xs:complexType name="WrapperTargetBase" abstract="true">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="target" type="Target" minOccurs="1" maxOccurs="1" />
+          <xs:element name="wrapper-target" type="WrapperTargetBase" minOccurs="1" maxOccurs="1" />
+          <xs:element name="compound-target" type="CompoundTargetBase" minOccurs="1" maxOccurs="1" />
+          <xs:element name="target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+          <xs:element name="wrapper-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+          <xs:element name="compound-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+        </xs:choice>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="CompoundTargetBase" abstract="true">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="target" type="Target" minOccurs="1" maxOccurs="unbounded" />
+          <xs:element name="wrapper-target" type="WrapperTargetBase" minOccurs="1" maxOccurs="1" />
+          <xs:element name="compound-target" type="CompoundTargetBase" minOccurs="1" maxOccurs="1" />
+          <xs:element name="target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+          <xs:element name="wrapper-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+          <xs:element name="compound-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
+        </xs:choice>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Filter" abstract="true"></xs:complexType>
+  <xs:complexType name="TimeSource" abstract="true"></xs:complexType>
+  <xs:simpleType name="SimpleLayoutAttribute">
+    <xs:restriction base="xs:string">
+      <xs:pattern value=".*" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="Condition">
+    <xs:restriction base="xs:string">
+      <xs:minLength value="1" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="AsyncWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="batchSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="forceLockingQueue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="fullBatchSizeWriteLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="overflowAction" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction" />
+          <xs:element name="queueLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="timeToSleepBetweenBatches" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="batchSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of log events that should be processed in a batch by the lazy writer thread.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="forceLockingQueue" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Whether to use the locking queue, instead of a lock-free concurrent queue The locking queue is less concurrent when many logger threads, but reduces memory allocation</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="fullBatchSizeWriteLimit" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Limit of full s to write before yielding into  Performance is better when writing many small batches, than writing a single large batch</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="overflowAction" type="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when the lazy writer thread request queue count exceeds the set limit.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="queueLimit" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Limit on the number of requests in the lazy writer thread request queue.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="timeToSleepBetweenBatches" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Time in milliseconds to sleep between batches. (1 or less means trigger on new activity)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Grow" />
+      <xs:enumeration value="Discard" />
+      <xs:enumeration value="Block" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="AutoFlushWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="asyncFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="flushOnConditionOnly" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="asyncFlush" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Delay the flush until the LogEvent has been confirmed as written</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="condition" type="Condition">
+          <xs:annotation>
+            <xs:documentation>Condition expression. Log events who meet this condition will cause a flush on the wrapped target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="flushOnConditionOnly" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Only flush when LogEvent matches condition. Ignore explicit-flush, config-reload-flush and shutdown-flush</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="BufferingWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="bufferSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="flushTimeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="overflowAction" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.BufferingTargetWrapperOverflowAction" />
+          <xs:element name="slidingTimeout" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="bufferSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of log events to be buffered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="flushTimeout" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="overflowAction" type="NLog.Targets.Wrappers.BufferingTargetWrapperOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action to take if the buffer overflows.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="slidingTimeout" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to use sliding timeout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.Wrappers.BufferingTargetWrapperOverflowAction">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Flush" />
+      <xs:enumeration value="Discard" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="Chainsaw">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
+          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
+          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
+          <xs:element name="sslProtocols" minOccurs="0" maxOccurs="1" type="System.Security.Authentication.SslProtocols" />
+          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepAliveTimeSeconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.NLogViewerParameterInfo" />
+          <xs:element name="ndlcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="includeSourceInfo" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="loggerName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="includeNLogData" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeCallSite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="appInfo" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="ndcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Encoding to be used.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Instance of  that is used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="lineEnding" type="LineEndingMode">
+          <xs:annotation>
+            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxMessageSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum message size in bytes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="newLine" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="address" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Network address.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="connectionCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepConnection" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxConnections" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="sslProtocols" type="System.Security.Authentication.SslProtocols">
+          <xs:annotation>
+            <xs:documentation>Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxQueueSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum queue size.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepAliveTimeSeconds" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>The number of seconds a connection will remain idle before the first keep-alive probe is sent</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ndlcItemSeparator" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>NDLC item separator.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeSourceInfo" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include source info (file name and line number) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="loggerName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Renderer for log4j:event logger-xml-attribute (Default ${logger})</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNLogData" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include NLog-specific extensions to log4j schema.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  stack.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  stack contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeCallSite" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include call site (class and method name) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeAllProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to include all properties from the log events</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="appInfo" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>AppInfo field. By default it's the friendly name of the current AppDomain.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ndcItemSeparator" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>NDC item separator.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.NetworkTargetConnectionsOverflowAction">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="AllowNewConnnection" />
+      <xs:enumeration value="DiscardMessage" />
+      <xs:enumeration value="Block" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.NetworkTargetOverflowAction">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Error" />
+      <xs:enumeration value="Split" />
+      <xs:enumeration value="Discard" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="System.Security.Authentication.SslProtocols">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="None" />
+      <xs:enumeration value="Ssl2" />
+      <xs:enumeration value="Ssl3" />
+      <xs:enumeration value="Tls" />
+      <xs:enumeration value="Tls11" />
+      <xs:enumeration value="Tls12" />
+      <xs:enumeration value="Tls13" />
+      <xs:enumeration value="Default" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="NLog.Targets.NLogViewerParameterInfo">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="includeEmptyValue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+    </xs:choice>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout that should be use to calculate the value for the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Viewer parameter name.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeEmptyValue" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Whether an attribute with empty value should be included in the output</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="ColoredConsole">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="enableAnsiOutput" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="errorStream" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="detectOutputRedirected" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="useDefaultRowHighlightingRules" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="highlight-row" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleRowHighlightingRule" />
+          <xs:element name="highlight-word" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleWordHighlightingRule" />
+          <xs:element name="autoFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text to be rendered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="detectConsoleAvailable" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="enableAnsiOutput" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Enables output using ANSI Color Codes</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>The encoding for writing messages to the .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="errorStream" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether the error stream (stderr) should be used instead of the output stream (stdout).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="detectOutputRedirected" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to auto-check if the console has been redirected to file - Disables coloring logic when System.Console.IsOutputRedirected = true</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useDefaultRowHighlightingRules" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to use default row highlighting rules.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="autoFlush" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to auto-flush after </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.ConsoleOutputColor">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Black" />
+      <xs:enumeration value="DarkBlue" />
+      <xs:enumeration value="DarkGreen" />
+      <xs:enumeration value="DarkCyan" />
+      <xs:enumeration value="DarkRed" />
+      <xs:enumeration value="DarkMagenta" />
+      <xs:enumeration value="DarkYellow" />
+      <xs:enumeration value="Gray" />
+      <xs:enumeration value="DarkGray" />
+      <xs:enumeration value="Blue" />
+      <xs:enumeration value="Green" />
+      <xs:enumeration value="Cyan" />
+      <xs:enumeration value="Red" />
+      <xs:enumeration value="Magenta" />
+      <xs:enumeration value="Yellow" />
+      <xs:enumeration value="White" />
+      <xs:enumeration value="NoChange" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="NLog.Targets.ConsoleRowHighlightingRule">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
+      <xs:element name="backgroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
+      <xs:element name="foregroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
+    </xs:choice>
+    <xs:attribute name="condition" type="Condition">
+      <xs:annotation>
+        <xs:documentation>Condition that must be met in order to set the specified foreground and background color.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="backgroundColor" type="NLog.Targets.ConsoleOutputColor">
+      <xs:annotation>
+        <xs:documentation>Background color.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="foregroundColor" type="NLog.Targets.ConsoleOutputColor">
+      <xs:annotation>
+        <xs:documentation>Foreground color.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLog.Targets.ConsoleWordHighlightingRule">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="compileRegex" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="regex" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="text" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="wholeWords" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="backgroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
+      <xs:element name="foregroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
+    </xs:choice>
+    <xs:attribute name="compileRegex" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="ignoreCase" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to ignore case when comparing texts.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="regex" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Regular expression to be matched. You must specify either text or regex.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="text" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Text to be matched. You must specify either text or regex.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="wholeWords" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to match whole words only.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="backgroundColor" type="NLog.Targets.ConsoleOutputColor">
+      <xs:annotation>
+        <xs:documentation>Background color.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="foregroundColor" type="NLog.Targets.ConsoleOutputColor">
+      <xs:annotation>
+        <xs:documentation>Foreground color.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="Console">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="error" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="autoFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="writeBuffer" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text to be rendered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="detectConsoleAvailable" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>The encoding for writing messages to the .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="error" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to send the log messages to the standard error instead of the standard output.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="autoFlush" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to auto-flush after </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="writeBuffer" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Whether to enable batch writing using char[]-buffers, instead of using </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Database">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="useTransactions" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="dbUserName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="dbProvider" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="dbPassword" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="dbDatabase" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="connectionStringName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="connectionString" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="dbHost" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="installConnectionString" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="install-command" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseCommandInfo" />
+          <xs:element name="uninstall-command" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseCommandInfo" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseParameterInfo" />
+          <xs:element name="commandText" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="commandType" minOccurs="0" maxOccurs="1" type="System.Data.CommandType" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useTransactions" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="dbUserName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="dbProvider" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the database provider.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="dbPassword" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepConnection" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to keep the database connection open between the log events.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="dbDatabase" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="connectionStringName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the connection string (as specified in &lt;connectionStrings&gt; configuration section.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="connectionString" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="dbHost" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="installConnectionString" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="commandText" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text of the SQL command to be run on each log level.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="commandType" type="System.Data.CommandType">
+          <xs:annotation>
+            <xs:documentation>Type of the SQL command to be run on each log level.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="System.Data.CommandType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Text" />
+      <xs:enumeration value="StoredProcedure" />
+      <xs:enumeration value="TableDirect" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="NLog.Targets.DatabaseCommandInfo">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="commandType" minOccurs="0" maxOccurs="1" type="System.Data.CommandType" />
+      <xs:element name="connectionString" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="ignoreFailures" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseParameterInfo" />
+      <xs:element name="text" minOccurs="0" maxOccurs="1" type="Layout" />
+    </xs:choice>
+    <xs:attribute name="commandType" type="System.Data.CommandType">
+      <xs:annotation>
+        <xs:documentation>Type of the command.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="connectionString" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Connection string to run the command against. If not provided, connection string from the target is used.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="ignoreFailures" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to ignore failures.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="text" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Command text.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLog.Targets.DatabaseParameterInfo">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="dbType" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="size" minOccurs="0" maxOccurs="1" type="xs:integer" />
+      <xs:element name="precision" minOccurs="0" maxOccurs="1" type="xs:byte" />
+      <xs:element name="scale" minOccurs="0" maxOccurs="1" type="xs:byte" />
+      <xs:element name="parameterType" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="format" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="culture" minOccurs="0" maxOccurs="1" type="xs:string" />
+    </xs:choice>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Database parameter name.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout that should be use to calculate the value for the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="dbType" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Database parameter DbType.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="size" type="xs:integer">
+      <xs:annotation>
+        <xs:documentation>Database parameter size.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="precision" type="xs:byte">
+      <xs:annotation>
+        <xs:documentation>Database parameter precision.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="scale" type="xs:byte">
+      <xs:annotation>
+        <xs:documentation>Database parameter scale.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="parameterType" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Type of the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="format" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Convert format of the database parameter value .</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="culture" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Culture used for parsing parameter string-value for type-conversion</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="Debugger">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text to be rendered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Debug">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="EventLog">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="category" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="entryType" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="eventId" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="log" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="machineName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="maxKilobytes" minOccurs="0" maxOccurs="1" type="xs:long" />
+          <xs:element name="maxMessageLength" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="source" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.EventLogTargetOverflowAction" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="category" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout that renders event Category.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="entryType" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Optional entry type. When not set, or when not convertible to  then determined by </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="eventId" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout that renders event ID.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="log" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the Event Log to write to. This can be System, Application or any user-defined name.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="machineName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the machine on which Event Log service is running.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxKilobytes" type="xs:long">
+          <xs:annotation>
+            <xs:documentation>Maximum Event log size in kilobytes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxMessageLength" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Message length limit to write to the Event Log.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="source" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Value to be used as the event Source.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onOverflow" type="NLog.Targets.EventLogTargetOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action to take if the message is larger than the  option.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.EventLogTargetOverflowAction">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Truncate" />
+      <xs:enumeration value="Split" />
+      <xs:enumeration value="Discard" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="FallbackGroup">
+    <xs:complexContent>
+      <xs:extension base="CompoundTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="returnToFirstOnSuccess" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="returnToFirstOnSuccess" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to return to the first target after any successful write.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="File">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
+          <xs:element name="enableArchiveFileCompression" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="archiveNumbering" minOccurs="0" maxOccurs="1" type="NLog.Targets.ArchiveNumberingMode" />
+          <xs:element name="archiveFileName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="archiveFileKind" minOccurs="0" maxOccurs="1" type="NLog.Targets.FilePathKind" />
+          <xs:element name="archiveEvery" minOccurs="0" maxOccurs="1" type="NLog.Targets.FileArchivePeriod" />
+          <xs:element name="archiveAboveSize" minOccurs="0" maxOccurs="1" type="xs:long" />
+          <xs:element name="maxArchiveFiles" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="writeFooterOnArchivingOnly" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxLogFilenames" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="fileNameKind" minOccurs="0" maxOccurs="1" type="NLog.Targets.FilePathKind" />
+          <xs:element name="forceManaged" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="forceMutexConcurrentWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="replaceFileContentsOnEachWrite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="writeBom" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="enableFileDelete" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="fileName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="archiveDateFormat" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="archiveOldFileOnStartup" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="cleanupFileName" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="createDirs" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="deleteOldFileOnStartup" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="fileAttributes" minOccurs="0" maxOccurs="1" type="NLog.Targets.Win32FileAttributes" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="networkWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="openFileCacheTimeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="openFileCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepFileOpen" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="discardAll" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="concurrentWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="concurrentWriteAttempts" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="concurrentWriteAttemptDelay" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="bufferSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="openFileFlushTimeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="autoFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text to be rendered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>File encoding.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="lineEnding" type="LineEndingMode">
+          <xs:annotation>
+            <xs:documentation>Line ending mode.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="enableArchiveFileCompression" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to compress archive files into the zip archive format.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveNumbering" type="NLog.Targets.ArchiveNumberingMode">
+          <xs:annotation>
+            <xs:documentation>Way file archives are numbered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveFileName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Name of the file to be used for an archive.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveFileKind" type="NLog.Targets.FilePathKind">
+          <xs:annotation>
+            <xs:documentation>Is the  an absolute or relative path?</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveEvery" type="NLog.Targets.FileArchivePeriod">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to automatically archive log files every time the specified time passes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveAboveSize" type="xs:long">
+          <xs:annotation>
+            <xs:documentation>Size in bytes above which log files will be automatically archived. Warning: combining this with  isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxArchiveFiles" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum number of archive files that should be kept.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="writeFooterOnArchivingOnly" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether the footer should be written only when the file is archived.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxLogFilenames" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum number of log file names that should be stored as existing.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="fileNameKind" type="NLog.Targets.FilePathKind">
+          <xs:annotation>
+            <xs:documentation>Is the  an absolute or relative path?</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="forceManaged" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="forceMutexConcurrentWrites" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether file creation calls should be synchronized by a system global mutex.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="replaceFileContentsOnEachWrite" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to replace file contents on each write instead of appending log message at the end.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="writeBom" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to write BOM (byte order mark) in created files</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="enableFileDelete" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to enable log file(s) to be deleted.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="fileName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Name of the file to write to.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveDateFormat" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Value specifying the date format to use when archiving files.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="archiveOldFileOnStartup" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to archive old log file on startup.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="cleanupFileName" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="createDirs" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to create directories if they do not exist.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="deleteOldFileOnStartup" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to delete old log file on startup.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="fileAttributes" type="NLog.Targets.Win32FileAttributes">
+          <xs:annotation>
+            <xs:documentation>File attributes (Windows only).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="networkWrites" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether concurrent writes to the log file by multiple processes on different network hosts.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="openFileCacheTimeout" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="openFileCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepFileOpen" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to keep log file open instead of opening and closing it on each logging event.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="discardAll" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="concurrentWrites" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether concurrent writes to the log file by multiple processes on the same host.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="concurrentWriteAttempts" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of times the write is appended on the file before NLog discards the log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="concurrentWriteAttemptDelay" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Delay in milliseconds to wait before attempting to write to the file again.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="bufferSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Log file buffer size in bytes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="openFileFlushTimeout" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum number of seconds before open files are flushed. If this number is negative or zero the files are not flushed by timer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="autoFlush" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to automatically flush the file buffers after each log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.ArchiveNumberingMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Sequence" />
+      <xs:enumeration value="Rolling" />
+      <xs:enumeration value="Date" />
+      <xs:enumeration value="DateAndSequence" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.FilePathKind">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Unknown" />
+      <xs:enumeration value="Relative" />
+      <xs:enumeration value="Absolute" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.FileArchivePeriod">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="None" />
+      <xs:enumeration value="Year" />
+      <xs:enumeration value="Month" />
+      <xs:enumeration value="Day" />
+      <xs:enumeration value="Hour" />
+      <xs:enumeration value="Minute" />
+      <xs:enumeration value="Sunday" />
+      <xs:enumeration value="Monday" />
+      <xs:enumeration value="Tuesday" />
+      <xs:enumeration value="Wednesday" />
+      <xs:enumeration value="Thursday" />
+      <xs:enumeration value="Friday" />
+      <xs:enumeration value="Saturday" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.Win32FileAttributes">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="ReadOnly" />
+      <xs:enumeration value="Hidden" />
+      <xs:enumeration value="System" />
+      <xs:enumeration value="Archive" />
+      <xs:enumeration value="Device" />
+      <xs:enumeration value="Normal" />
+      <xs:enumeration value="Temporary" />
+      <xs:enumeration value="SparseFile" />
+      <xs:enumeration value="ReparsePoint" />
+      <xs:enumeration value="Compressed" />
+      <xs:enumeration value="NotContentIndexed" />
+      <xs:enumeration value="Encrypted" />
+      <xs:enumeration value="WriteThrough" />
+      <xs:enumeration value="NoBuffering" />
+      <xs:enumeration value="DeleteOnClose" />
+      <xs:enumeration value="PosixSemantics" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="FilteringWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
+          <xs:element name="filter" minOccurs="0" maxOccurs="1" type="Filter" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="condition" type="Condition">
+          <xs:annotation>
+            <xs:documentation>Condition expression. Log events who meet this condition will be forwarded to the wrapped target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="ImpersonatingWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="domain" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="impersonationLevel" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.SecurityImpersonationLevel" />
+          <xs:element name="logOnProvider" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.LogOnProviderType" />
+          <xs:element name="logOnType" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.SecurityLogOnType" />
+          <xs:element name="password" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="revertToSelf" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="userName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="domain" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Windows domain name to change context to.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="impersonationLevel" type="NLog.Targets.Wrappers.SecurityImpersonationLevel">
+          <xs:annotation>
+            <xs:documentation>Required impersonation level.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="logOnProvider" type="NLog.Targets.Wrappers.LogOnProviderType">
+          <xs:annotation>
+            <xs:documentation>Type of the logon provider.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="logOnType" type="NLog.Targets.Wrappers.SecurityLogOnType">
+          <xs:annotation>
+            <xs:documentation>Logon Type.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>User account password.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="revertToSelf" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to revert to the credentials of the process instead of impersonating another user.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="userName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Username to change context to.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.Wrappers.SecurityImpersonationLevel">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Anonymous" />
+      <xs:enumeration value="Identification" />
+      <xs:enumeration value="Impersonation" />
+      <xs:enumeration value="Delegation" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.Wrappers.LogOnProviderType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Default" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.Wrappers.SecurityLogOnType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Interactive" />
+      <xs:enumeration value="Network" />
+      <xs:enumeration value="Batch" />
+      <xs:enumeration value="Service" />
+      <xs:enumeration value="NetworkClearText" />
+      <xs:enumeration value="NewCredentials" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="LimitingWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="interval" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="messageLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="interval" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Interval in which messages will be written up to the  number of messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="messageLimit" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum allowed number of messages written per .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="LogReceiverService">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="endpointAddress" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="endpointConfigurationName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="useOneWayContract" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="clientId" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="includeEventProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
+          <xs:element name="useBinaryEncoding" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="endpointAddress" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Endpoint address.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="endpointConfigurationName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the endpoint configuration in WCF configuration file.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useOneWayContract" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="clientId" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Client ID.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeEventProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include per-event properties in the payload sent to the server.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useBinaryEncoding" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to use binary message encoding.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="NLog.Targets.MethodCallParameter">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="parameterType" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="type" minOccurs="0" maxOccurs="1" type="xs:string" />
+    </xs:choice>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout that should be use to calculate the value for the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Name of the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="parameterType" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Type of the parameter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="type" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Type of the parameter. Obsolete alias for </xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="Mail">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="replaceNewlineWithBrTagInHtml" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="priority" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="bcc" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="cc" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="addNewLines" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="html" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="from" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="body" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="subject" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="to" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="timeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="smtpServer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="smtpAuthentication" minOccurs="0" maxOccurs="1" type="NLog.Targets.SmtpAuthenticationMode" />
+          <xs:element name="smtpUserName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="smtpPassword" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="enableSsl" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="smtpPort" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="useSystemNetMailSettings" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="pickupDirectoryLocation" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="deliveryMethod" minOccurs="0" maxOccurs="1" type="System.Net.Mail.SmtpDeliveryMethod" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Text to be rendered.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="replaceNewlineWithBrTagInHtml" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether NewLine characters in the body should be replaced with  tags.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="priority" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Priority used for sending mails.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Encoding to be used for sending e-mail.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="bcc" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="cc" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="addNewLines" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to add new lines between log entries.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="html" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to send message as HTML instead of plain text.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="from" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Sender's email address (e.g. joe@domain.com).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="body" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Mail message body (repeated for each log message send in one mail).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="subject" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Mail subject.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="to" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="timeout" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Indicates the SMTP client timeout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="smtpServer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>SMTP Server to be used for sending.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="smtpAuthentication" type="NLog.Targets.SmtpAuthenticationMode">
+          <xs:annotation>
+            <xs:documentation>SMTP Authentication mode.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="smtpUserName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic").</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="smtpPassword" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic").</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="enableSsl" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="smtpPort" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Port number that SMTP Server is listening on.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useSystemNetMailSettings" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether the default Settings from System.Net.MailSettings should be used.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="pickupDirectoryLocation" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Folder where applications save mail messages to be processed by the local SMTP server.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="deliveryMethod" type="System.Net.Mail.SmtpDeliveryMethod">
+          <xs:annotation>
+            <xs:documentation>Specifies how outgoing email messages will be handled.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.SmtpAuthenticationMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="None" />
+      <xs:enumeration value="Basic" />
+      <xs:enumeration value="Ntlm" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="System.Net.Mail.SmtpDeliveryMethod">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Network" />
+      <xs:enumeration value="SpecifiedPickupDirectory" />
+      <xs:enumeration value="PickupDirectoryFromIis" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="Memory">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="maxLogsCount" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxLogsCount" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Max number of items to have in memory</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="MethodCall">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="className" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="methodName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="className" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Class name.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="methodName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Network">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
+          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
+          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
+          <xs:element name="sslProtocols" minOccurs="0" maxOccurs="1" type="System.Security.Authentication.SslProtocols" />
+          <xs:element name="keepAliveTimeSeconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Encoding to be used.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="lineEnding" type="LineEndingMode">
+          <xs:annotation>
+            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxMessageSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum message size in bytes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="newLine" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="address" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Network address.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="connectionCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepConnection" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxConnections" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxQueueSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum queue size.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="sslProtocols" type="System.Security.Authentication.SslProtocols">
+          <xs:annotation>
+            <xs:documentation>Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepAliveTimeSeconds" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>The number of seconds a connection will remain idle before the first keep-alive probe is sent</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="NLogViewer">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
+          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
+          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
+          <xs:element name="sslProtocols" minOccurs="0" maxOccurs="1" type="System.Security.Authentication.SslProtocols" />
+          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="keepAliveTimeSeconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.NLogViewerParameterInfo" />
+          <xs:element name="ndlcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="includeSourceInfo" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="loggerName" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="includeNLogData" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeCallSite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="appInfo" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="ndcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Encoding to be used.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Instance of  that is used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="lineEnding" type="LineEndingMode">
+          <xs:annotation>
+            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxMessageSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum message size in bytes.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="newLine" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="address" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Network address.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="connectionCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepConnection" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxConnections" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
+          <xs:annotation>
+            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="sslProtocols" type="System.Security.Authentication.SslProtocols">
+          <xs:annotation>
+            <xs:documentation>Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxQueueSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Maximum queue size.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="keepAliveTimeSeconds" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>The number of seconds a connection will remain idle before the first keep-alive probe is sent</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ndlcItemSeparator" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>NDLC item separator.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeSourceInfo" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include source info (file name and line number) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="loggerName" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Renderer for log4j:event logger-xml-attribute (Default ${logger})</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNLogData" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include NLog-specific extensions to log4j schema.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  stack.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  stack contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeCallSite" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include call site (class and method name) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeAllProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to include all properties from the log events</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="appInfo" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>AppInfo field. By default it's the friendly name of the current AppDomain.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ndcItemSeparator" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>NDC item separator.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Null">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="formatMessage" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="formatMessage" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to perform layout calculation.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="OutputDebugString">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="PerfCounter">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="autoCreate" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="categoryName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="counterHelp" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="counterName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="counterType" minOccurs="0" maxOccurs="1" type="System.Diagnostics.PerformanceCounterType" />
+          <xs:element name="incrementValue" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="instanceName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="autoCreate" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether performance counter should be automatically created.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="categoryName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the performance counter category.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="counterHelp" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Counter help text.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="counterName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the performance counter.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="counterType" type="System.Diagnostics.PerformanceCounterType">
+          <xs:annotation>
+            <xs:documentation>Performance counter type.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="incrementValue" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>The value by which to increment the counter.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="instanceName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Performance counter instance name.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="System.Diagnostics.PerformanceCounterType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="NumberOfItems32" />
+      <xs:enumeration value="NumberOfItems64" />
+      <xs:enumeration value="NumberOfItemsHEX32" />
+      <xs:enumeration value="NumberOfItemsHEX64" />
+      <xs:enumeration value="RateOfCountsPerSecond32" />
+      <xs:enumeration value="RateOfCountsPerSecond64" />
+      <xs:enumeration value="CountPerTimeInterval32" />
+      <xs:enumeration value="CountPerTimeInterval64" />
+      <xs:enumeration value="RawFraction" />
+      <xs:enumeration value="RawBase" />
+      <xs:enumeration value="AverageTimer32" />
+      <xs:enumeration value="AverageBase" />
+      <xs:enumeration value="AverageCount64" />
+      <xs:enumeration value="SampleFraction" />
+      <xs:enumeration value="SampleCounter" />
+      <xs:enumeration value="SampleBase" />
+      <xs:enumeration value="CounterTimer" />
+      <xs:enumeration value="CounterTimerInverse" />
+      <xs:enumeration value="Timer100Ns" />
+      <xs:enumeration value="Timer100NsInverse" />
+      <xs:enumeration value="ElapsedTime" />
+      <xs:enumeration value="CounterMultiTimer" />
+      <xs:enumeration value="CounterMultiTimerInverse" />
+      <xs:enumeration value="CounterMultiTimer100Ns" />
+      <xs:enumeration value="CounterMultiTimer100NsInverse" />
+      <xs:enumeration value="CounterMultiBase" />
+      <xs:enumeration value="CounterDelta32" />
+      <xs:enumeration value="CounterDelta64" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="PostFilteringWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="defaultFilter" minOccurs="0" maxOccurs="1" type="Condition" />
+          <xs:element name="when" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.Wrappers.FilteringRule" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="defaultFilter" type="Condition">
+          <xs:annotation>
+            <xs:documentation>Default filter to be applied when no specific rule matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="NLog.Targets.Wrappers.FilteringRule">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="exists" minOccurs="0" maxOccurs="1" type="Condition" />
+      <xs:element name="filter" minOccurs="0" maxOccurs="1" type="Condition" />
+    </xs:choice>
+    <xs:attribute name="exists" type="Condition">
+      <xs:annotation>
+        <xs:documentation>Condition to be tested.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="filter" type="Condition">
+      <xs:annotation>
+        <xs:documentation>Resulting filter to be applied when the condition matches.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="RandomizeGroup">
+    <xs:complexContent>
+      <xs:extension base="CompoundTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="RepeatingWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="repeatCount" minOccurs="0" maxOccurs="1" type="xs:integer" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="repeatCount" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of times to repeat each log message.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="RetryingWrapper">
+    <xs:complexContent>
+      <xs:extension base="WrapperTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="retryCount" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="retryDelayMilliseconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="retryCount" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Number of retries that should be attempted on the wrapped target in case of a failure.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="retryDelayMilliseconds" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Time to wait between retries in milliseconds.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="RoundRobinGroup">
+    <xs:complexContent>
+      <xs:extension base="CompoundTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="SplitGroup">
+    <xs:complexContent>
+      <xs:extension base="CompoundTargetBase">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Trace">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="rawWrite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout used to format log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="rawWrite" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Always use  independent of </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="WebService">
+    <xs:complexContent>
+      <xs:extension base="Target">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeBOM" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="methodName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="namespace" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="protocol" minOccurs="0" maxOccurs="1" type="NLog.Targets.WebServiceProtocol" />
+          <xs:element name="proxyAddress" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="url" minOccurs="0" maxOccurs="1" type="xs:anyURI" />
+          <xs:element name="escapeDataNLogLegacy" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="escapeDataRfc3986" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="preAuthenticate" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="xmlRoot" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="xmlRootNamespace" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="header" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
+          <xs:element name="proxyType" minOccurs="0" maxOccurs="1" type="NLog.Targets.WebServiceProxyType" />
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the target.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeBOM" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Should we include the BOM (Byte-order-mark) for UTF? Influences the  property. This will only work for UTF-8.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="methodName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Web service method name. Only used with Soap.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="namespace" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Web service namespace. Only used with Soap.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="protocol" type="NLog.Targets.WebServiceProtocol">
+          <xs:annotation>
+            <xs:documentation>Protocol to be used when calling web service.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="proxyAddress" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Custom proxy address, include port separated by a colon</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Encoding.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="url" type="xs:anyURI">
+          <xs:annotation>
+            <xs:documentation>Web service URL.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="escapeDataNLogLegacy" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Value whether escaping be done according to the old NLog style (Very non-standard)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="escapeDataRfc3986" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="preAuthenticate" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in  parameters)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="xmlRoot" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see  and ).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="xmlRootNamespace" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>(optional) root namespace of the XML document, if POST of XML document chosen. (see  and ).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="proxyType" type="NLog.Targets.WebServiceProxyType">
+          <xs:annotation>
+            <xs:documentation>Proxy configuration when calling web service</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Targets.WebServiceProtocol">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Soap11" />
+      <xs:enumeration value="Soap12" />
+      <xs:enumeration value="HttpPost" />
+      <xs:enumeration value="HttpGet" />
+      <xs:enumeration value="JsonPost" />
+      <xs:enumeration value="XmlPost" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Targets.WebServiceProxyType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="DefaultWebProxy" />
+      <xs:enumeration value="AutoProxy" />
+      <xs:enumeration value="NoProxy" />
+      <xs:enumeration value="ProxyAddress" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="CompoundLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="layout" minOccurs="0" maxOccurs="unbounded" type="Layout" />
+        </xs:choice>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Layout">
+    <xs:choice minOccurs="0" maxOccurs="unbounded" />
+  </xs:complexType>
+  <xs:complexType name="CsvLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="column" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.CsvColumn" />
+          <xs:element name="customColumnDelimiter" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="delimiter" minOccurs="0" maxOccurs="1" type="NLog.Layouts.CsvColumnDelimiterMode" />
+          <xs:element name="quoteChar" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="quoting" minOccurs="0" maxOccurs="1" type="NLog.Layouts.CsvQuotingMode" />
+          <xs:element name="withHeader" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer layout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header layout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Body layout (can be repeated multiple times).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="customColumnDelimiter" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom').</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="delimiter" type="NLog.Layouts.CsvColumnDelimiterMode">
+          <xs:annotation>
+            <xs:documentation>Column delimiter.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="quoteChar" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Quote Character.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="quoting" type="NLog.Layouts.CsvQuotingMode">
+          <xs:annotation>
+            <xs:documentation>Quoting mode.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="withHeader" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether CVS should include header.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="NLog.Layouts.CsvQuotingMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="All" />
+      <xs:enumeration value="Nothing" />
+      <xs:enumeration value="Auto" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="NLog.Layouts.CsvColumnDelimiterMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Auto" />
+      <xs:enumeration value="Comma" />
+      <xs:enumeration value="Semicolon" />
+      <xs:enumeration value="Tab" />
+      <xs:enumeration value="Pipe" />
+      <xs:enumeration value="Space" />
+      <xs:enumeration value="Custom" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="NLog.Layouts.CsvColumn">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="quoting" minOccurs="0" maxOccurs="1" type="NLog.Layouts.CsvQuotingMode" />
+    </xs:choice>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout of the column.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Name of the column.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="quoting" type="NLog.Layouts.CsvQuotingMode">
+      <xs:annotation>
+        <xs:documentation>Override of Quoting mode</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="JsonLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="attribute" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.JsonAttribute" />
+          <xs:element name="excludeProperties" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeGdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxRecursionLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="renderEmptyObject" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="suppressSpaces" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="escapeForwardSlash" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="excludeProperties" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>List of property names to exclude when  is true</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeAllProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to include all properties from the log event (as JSON)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeGdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxRecursionLimit" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>How far should the JSON serializer follow object references before backing off</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="renderEmptyObject" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to render the empty object value {}</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="suppressSpaces" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to suppress the extra spaces in the output json</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="escapeForwardSlash" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Should forward slashes be escaped? If true, / will be converted to \/</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="NLog.Layouts.JsonAttribute">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="encode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="escapeUnicode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="includeEmptyValue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="escapeForwardSlash" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+    </xs:choice>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout that will be rendered as the attribute's value.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Name of the attribute.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="encode" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Determines whether or not this attribute will be Json encoded.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="escapeUnicode" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to escape non-ascii characters</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeEmptyValue" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Whether an attribute with empty value should be included in the output</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="escapeForwardSlash" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Should forward slashes be escaped? If true, / will be converted to \/</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="LayoutWithHeaderAndFooter">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+        </xs:choice>
+        <xs:attribute name="footer" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Footer layout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="header" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Header layout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Body layout (can be repeated multiple times).</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="Log4JXmlEventLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeCallSite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeNdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeSourceInfo" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.NLogViewerParameterInfo" />
+        </xs:choice>
+        <xs:attribute name="includeAllProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to include all properties from the log events</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeCallSite" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include call site (class and method name) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  stack.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeNdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  stack.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeSourceInfo" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include source info (file name and line number) in the information sent over the network.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="SimpleLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="text" minOccurs="0" maxOccurs="1" type="xs:string" />
+        </xs:choice>
+        <xs:attribute name="text" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Layout text.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="XmlLayout">
+    <xs:complexContent>
+      <xs:extension base="Layout">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="excludeProperties" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="maxRecursionLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="propertiesCollectionItemName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="propertiesElementKeyAttribute" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="propertiesElementName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="propertiesElementValueAttribute" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="attribute" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.XmlAttribute" />
+          <xs:element name="elementName" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="element" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.XmlElement" />
+          <xs:element name="elementValue" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="includeEmptyValue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="indentXml" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="elementEncode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+        </xs:choice>
+        <xs:attribute name="excludeProperties" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>List of property names to exclude when  is true</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeAllProperties" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Option to include all properties from the log event (as XML)</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeMdlc" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxRecursionLimit" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>How far should the XML serializer follow object references before backing off</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="propertiesCollectionItemName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>XML element name to use for rendering IList-collections items</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="propertiesElementKeyAttribute" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="propertiesElementName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>XML element name to use when rendering properties</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="propertiesElementValueAttribute" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="elementName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Name of the root XML element</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="elementValue" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Value inside the root XML element</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeEmptyValue" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Whether a ElementValue with empty value should be included in the output</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="indentXml" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Auto indent and create new lines</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="elementEncode" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Determines whether or not this attribute will be Xml encoded.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="NLog.Layouts.XmlAttribute">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="encode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="includeEmptyValue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+    </xs:choice>
+    <xs:attribute name="layout" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Layout that will be rendered as the attribute's value.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Name of the attribute.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="encode" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Determines whether or not this attribute will be Xml encoded.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeEmptyValue" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Whether an attribute with empty value should be included in the output</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="NLog.Layouts.XmlElement">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element name="encode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="value" minOccurs="0" maxOccurs="1" type="Layout" />
+      <xs:element name="attribute" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.XmlAttribute" />
+      <xs:element name="element" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.XmlElement" />
+      <xs:element name="includeEmptyValue" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="indentXml" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="excludeProperties" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+      <xs:element name="maxRecursionLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
+      <xs:element name="propertiesCollectionItemName" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="propertiesElementKeyAttribute" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="propertiesElementName" minOccurs="0" maxOccurs="1" type="xs:string" />
+      <xs:element name="propertiesElementValueAttribute" minOccurs="0" maxOccurs="1" type="xs:string" />
+    </xs:choice>
+    <xs:attribute name="encode" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Determines whether or not this attribute will be Xml encoded.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="name" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>Name of the element</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="value" type="SimpleLayoutAttribute">
+      <xs:annotation>
+        <xs:documentation>Value inside the element</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeEmptyValue" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Whether a ElementValue with empty value should be included in the output</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="indentXml" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Auto indent and create new lines</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="excludeProperties" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>List of property names to exclude when  is true</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeAllProperties" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Option to include all properties from the log event (as XML)</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeMdc" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="includeMdlc" type="xs:boolean">
+      <xs:annotation>
+        <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="maxRecursionLimit" type="xs:integer">
+      <xs:annotation>
+        <xs:documentation>How far should the XML serializer follow object references before backing off</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="propertiesCollectionItemName" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>XML element name to use for rendering IList-collections items</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="propertiesElementKeyAttribute" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="propertiesElementName" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>XML element name to use when rendering properties</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="propertiesElementValueAttribute" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:complexType>
+  <xs:complexType name="when">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="condition" type="Condition">
+          <xs:annotation>
+            <xs:documentation>Condition expression.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:simpleType name="FilterResult">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="Neutral" />
+      <xs:enumeration value="Log" />
+      <xs:enumeration value="Ignore" />
+      <xs:enumeration value="LogFinal" />
+      <xs:enumeration value="IgnoreFinal" />
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:complexType name="whenContains">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="substring" minOccurs="0" maxOccurs="1" type="xs:string" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreCase" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="substring" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Substring to be matched.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="whenEqual">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="compareTo" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="compareTo" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>String to compare the layout to.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreCase" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="whenNotContains">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="substring" minOccurs="0" maxOccurs="1" type="xs:string" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreCase" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="substring" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Substring to be matched.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="whenNotEqual">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="compareTo" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="compareTo" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>String to compare the layout to.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreCase" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="whenRepeated">
+    <xs:complexContent>
+      <xs:extension base="Filter">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
+          <xs:element name="defaultFilterCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="includeFirst" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
+          <xs:element name="maxFilterCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="maxLength" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="timeoutSeconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="optimizeBufferDefaultLength" minOccurs="0" maxOccurs="1" type="xs:integer" />
+          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
+          <xs:element name="filterCountMessageAppendFormat" minOccurs="0" maxOccurs="1" type="xs:string" />
+          <xs:element name="filterCountPropertyName" minOccurs="0" maxOccurs="1" type="xs:string" />
+        </xs:choice>
+        <xs:attribute name="action" type="FilterResult">
+          <xs:annotation>
+            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="defaultFilterCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Default number of unique filter values to expect, will automatically increase if needed</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="includeFirst" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Applies the configured action to the initial logevent that starts the timeout period. Used to configure that it should ignore all events until timeout.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="layout" type="SimpleLayoutAttribute">
+          <xs:annotation>
+            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxFilterCacheSize" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Max number of unique filter values to expect simultaneously</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="maxLength" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Max length of filter values, will truncate if above limit</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="timeoutSeconds" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>How long before a filter expires, and logging is accepted again</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferDefaultLength" type="xs:integer">
+          <xs:annotation>
+            <xs:documentation>Default buffer size for the internal buffers</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>Reuse internal buffers, and doesn't have to constantly allocate new buffers</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="filterCountMessageAppendFormat" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Append FilterCount to the  when an event is no longer filtered</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="filterCountPropertyName" type="xs:string">
+          <xs:annotation>
+            <xs:documentation>Insert FilterCount value into  when an event is no longer filtered</xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="AccurateLocal">
+    <xs:complexContent>
+      <xs:extension base="TimeSource">
+        <xs:choice minOccurs="0" maxOccurs="unbounded" />
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="AccurateUTC">
+    <xs:complexContent>
+      <xs:extension base="TimeSource">
+        <xs:choice minOccurs="0" maxOccurs="unbounded" />
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="FastLocal">
+    <xs:complexContent>
+      <xs:extension base="TimeSource">
+        <xs:choice minOccurs="0" maxOccurs="unbounded" />
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="FastUTC">
+    <xs:complexContent>
+      <xs:extension base="TimeSource">
+        <xs:choice minOccurs="0" maxOccurs="unbounded" />
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git a/src/Version/Program.cs b/src/Version/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fd99572731651df448b1ac84e5030477dbc103b7
--- /dev/null
+++ b/src/Version/Program.cs
@@ -0,0 +1,15 @@
+using Coscine.ApiCommons;
+using Coscine.Configuration;
+
+namespace Coscine.Api.Version
+{
+    class Program : AbstractProgram<ConsulConfiguration>
+    {
+
+        static void Main(string[] args)
+        {
+            InitializeWebService<Startup>();
+        }
+
+    }
+}
diff --git a/src/Version/Properties/AssemblyInfo.cs b/src/Version/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1096c1aadb07e83e7ec581b1e51219b4d19548f5
--- /dev/null
+++ b/src/Version/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Version")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Version")]
+[assembly: AssemblyCopyright("Copyright ©  2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d942046b-88d3-44aa-856b-6a7b5a7dcbb0")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Version/Startup.cs b/src/Version/Startup.cs
new file mode 100644
index 0000000000000000000000000000000000000000..446ae55a923f1aaa9addb3f5b6f98603e45d6abc
--- /dev/null
+++ b/src/Version/Startup.cs
@@ -0,0 +1,12 @@
+using Coscine.ApiCommons;
+
+namespace Coscine.Api.Version
+{
+    public class Startup : AbstractDefaultStartup
+    {
+        public Startup()
+        {
+
+        }
+    }
+}
diff --git a/src/Version/Version.csproj b/src/Version/Version.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..1a86d83d1b7de756a95f2234e743802a0a879b1f
--- /dev/null
+++ b/src/Version/Version.csproj
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.props" Condition="Exists('..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.props')" />
+  <Import Project="..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props" Condition="Exists('..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props')" />
+  <Import Project="..\packages\NUnit.3.12.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.12.0\build\NUnit.props')" />
+  <Import Project="..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.props" Condition="Exists('..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.props')" />
+  <Import Project="..\packages\Microsoft.DiaSymReader.Native.1.7.0\build\Microsoft.DiaSymReader.Native.props" Condition="Exists('..\packages\Microsoft.DiaSymReader.Native.1.7.0\build\Microsoft.DiaSymReader.Native.props')" />
+  <Import Project="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\build\Microsoft.CodeAnalysis.Analyzers.props" Condition="Exists('..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\build\Microsoft.CodeAnalysis.Analyzers.props')" />
+  <Import Project="..\packages\Microsoft.AspNetCore.Razor.Design.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" Condition="Exists('..\packages\Microsoft.AspNetCore.Razor.Design.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props')" />
+  <Import Project="..\packages\linq2db.t4models.2.6.4\build\linq2db.t4models.props" Condition="Exists('..\packages\linq2db.t4models.2.6.4\build\linq2db.t4models.props')" />
+  <Import Project="..\packages\linq2db.SqlServer.2.6.4\build\linq2db.SqlServer.props" Condition="Exists('..\packages\linq2db.SqlServer.2.6.4\build\linq2db.SqlServer.props')" />
+  <Import Project="..\packages\EntityFramework.6.4.4\build\EntityFramework.props" Condition="Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" />
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{D942046B-88D3-44AA-856B-6A7B5A7DCBB0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Coscine.Api.Version</RootNamespace>
+    <AssemblyName>Coscine.Api.Version</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Aspose.Email, Version=20.10.0.0, Culture=neutral, PublicKeyToken=716fcc553a201e56, processorArchitecture=MSIL">
+      <HintPath>..\packages\Aspose.Email.20.10.0\lib\net40\Aspose.Email.dll</HintPath>
+    </Reference>
+    <Reference Include="Consul, Version=0.7.2.6, Culture=neutral, PublicKeyToken=20a6ad9a81df1d95, processorArchitecture=MSIL">
+      <HintPath>..\packages\Consul.0.7.2.6\lib\net45\Consul.dll</HintPath>
+    </Reference>
+    <Reference Include="Coscine.ApiCommons, Version=1.10.0.0, Culture=neutral, PublicKeyToken=af4c1345df96546b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Coscine.ApiCommons.1.10.0\lib\net461\Coscine.ApiCommons.dll</HintPath>
+    </Reference>
+    <Reference Include="Coscine.Configuration, Version=1.5.0.0, Culture=neutral, PublicKeyToken=ce3d7a32d7dc1e5a, processorArchitecture=MSIL">
+      <HintPath>..\packages\Coscine.Configuration.1.5.0\lib\net461\Coscine.Configuration.dll</HintPath>
+    </Reference>
+    <Reference Include="Coscine.Database, Version=1.24.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL">
+      <HintPath>..\packages\Coscine.Database.1.24.0\lib\net461\Coscine.Database.dll</HintPath>
+    </Reference>
+    <Reference Include="Coscine.Database.T4, Version=1.24.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL">
+      <HintPath>..\packages\Coscine.Database.1.24.0\lib\net461\Coscine.Database.T4.dll</HintPath>
+    </Reference>
+    <Reference Include="Coscine.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=e1ed402bc3f6525e, processorArchitecture=MSIL">
+      <HintPath>..\packages\Coscine.Logging.1.2.0\lib\net461\Coscine.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="linq2db, Version=3.1.1.0, Culture=neutral, PublicKeyToken=e41013125f9e410a, processorArchitecture=MSIL">
+      <HintPath>..\packages\linq2db.3.1.1\lib\net46\linq2db.dll</HintPath>
+    </Reference>
+    <Reference Include="LinqKit, Version=1.1.17.0, Culture=neutral, PublicKeyToken=bc217f8844052a91, processorArchitecture=MSIL">
+      <HintPath>..\packages\LinqKit.1.1.17\lib\net45\LinqKit.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Antiforgery, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Antiforgery.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authentication, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authentication.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authentication.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authentication.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authentication.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authentication.Core.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authentication.JwtBearer.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authorization, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authorization.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Authorization.Policy, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Authorization.Policy.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.Policy.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Connections.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Connections.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Cors, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Cors.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Cryptography.Internal, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Cryptography.Internal.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.DataProtection, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.DataProtection.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.DataProtection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Diagnostics, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Diagnostics.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Diagnostics.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Diagnostics.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Hosting, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Hosting.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Hosting.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Hosting.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Hosting.Server.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Html.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Html.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Http, Version=2.2.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Http.2.2.2\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Http.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Http.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Http.Extensions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Http.Extensions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Http.Features, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Http.Features.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.HttpOverrides, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.HttpOverrides.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.JsonPatch, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.JsonPatch.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.JsonPatch.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Localization, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Localization.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Localization.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.ApiExplorer, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.ApiExplorer.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Core, Version=2.2.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Core.2.2.2\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Cors, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Cors.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Cors.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.DataAnnotations, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.DataAnnotations.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Json, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Formatters.Json.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Localization, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Localization.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Localization.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Razor, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Razor.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\lib\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.RazorPages, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.RazorPages.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.RazorPages.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.TagHelpers, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.TagHelpers.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Mvc.ViewFeatures.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Razor, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Razor.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Razor.Language, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Razor.Language.2.2.0\lib\net46\Microsoft.AspNetCore.Razor.Language.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Razor.Runtime, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Razor.Runtime.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Runtime.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.ResponseCaching.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.ResponseCaching.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Routing, Version=2.2.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Routing.2.2.2\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Routing.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Routing.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Server.Kestrel.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Server.Kestrel.Core.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel.Https, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Server.Kestrel.Https.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=2.2.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.2.2.1\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.StaticFiles, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.StaticFiles.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.StaticFiles.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.AspNetCore.WebUtilities, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.AspNetCore.WebUtilities.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CodeAnalysis, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.CodeAnalysis.Common.3.0.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CodeAnalysis.CSharp, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.3.0.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CodeAnalysis.Razor, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.CodeAnalysis.Razor.2.2.0\lib\net46\Microsoft.CodeAnalysis.Razor.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.DotNet.PlatformAbstractions.2.1.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Caching.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Caching.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Caching.Memory, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Caching.Memory.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.Binder, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.Binder.2.2.4\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.EnvironmentVariables, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.FileExtensions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.FileExtensions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.DependencyInjection, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.DependencyInjection.2.2.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.DependencyModel, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.DependencyModel.2.1.0\lib\net451\Microsoft.Extensions.DependencyModel.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.FileProviders.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.FileProviders.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.FileProviders.Composite, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.FileProviders.Composite.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Composite.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.FileProviders.Embedded, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.FileProviders.Embedded.1.0.1\lib\netstandard1.0\Microsoft.Extensions.FileProviders.Embedded.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.FileProviders.Physical, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.FileProviders.Physical.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.FileSystemGlobbing, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.FileSystemGlobbing.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Hosting.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Hosting.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Localization, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Localization.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Localization.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Localization.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Logging, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Logging.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.ObjectPool, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.ObjectPool.2.2.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Options, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Options.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Primitives, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Primitives.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.WebEncoders, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.WebEncoders.2.2.0\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.IdentityModel.JsonWebTokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.IdentityModel.JsonWebTokens.5.5.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.IdentityModel.Logging, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.IdentityModel.Logging.5.5.0\lib\net461\Microsoft.IdentityModel.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.IdentityModel.Protocols, Version=5.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.IdentityModel.Protocols.5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect, Version=5.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.IdentityModel.Protocols.OpenIdConnect.5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.IdentityModel.Tokens, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.IdentityModel.Tokens.5.5.0\lib\net461\Microsoft.IdentityModel.Tokens.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Net.Http.Headers, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Net.Http.Headers.2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
+    </Reference>
+    <Reference Include="Namotion.Reflection, Version=1.0.11.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
+      <HintPath>..\packages\Namotion.Reflection.1.0.11\lib\net45\Namotion.Reflection.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json.Bson, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll</HintPath>
+    </Reference>
+    <Reference Include="NJsonSchema, Version=10.1.23.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
+      <HintPath>..\packages\NJsonSchema.10.1.23\lib\net45\NJsonSchema.dll</HintPath>
+    </Reference>
+    <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+      <HintPath>..\packages\NLog.4.6.8\lib\net45\NLog.dll</HintPath>
+    </Reference>
+    <Reference Include="NLog.Extensions.Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+      <HintPath>..\packages\NLog.Extensions.Logging.1.6.1\lib\net461\NLog.Extensions.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="NLog.Web.AspNetCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+      <HintPath>..\packages\NLog.Web.AspNetCore.4.9.0\lib\net461\NLog.Web.AspNetCore.dll</HintPath>
+    </Reference>
+    <Reference Include="NSwag.Annotations, Version=13.6.2.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
+      <HintPath>..\packages\NSwag.Annotations.13.6.2\lib\net45\NSwag.Annotations.dll</HintPath>
+    </Reference>
+    <Reference Include="NSwag.AspNetCore, Version=13.6.2.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
+      <HintPath>..\packages\NSwag.AspNetCore.13.6.2\lib\net451\NSwag.AspNetCore.dll</HintPath>
+    </Reference>
+    <Reference Include="NSwag.Core, Version=13.6.2.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
+      <HintPath>..\packages\NSwag.Core.13.6.2\lib\net45\NSwag.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="NSwag.Generation, Version=13.6.2.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
+      <HintPath>..\packages\NSwag.Generation.13.6.2\lib\net45\NSwag.Generation.dll</HintPath>
+    </Reference>
+    <Reference Include="NSwag.Generation.AspNetCore, Version=13.6.2.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
+      <HintPath>..\packages\NSwag.Generation.AspNetCore.13.6.2\lib\net451\NSwag.Generation.AspNetCore.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.framework, Version=3.12.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
+    </Reference>
+    <Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.ComponentModel.Annotations.4.5.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
+    </Reference>
+    <Reference Include="System.ComponentModel.Composition" />
+    <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data.OracleClient" />
+    <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.3.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Diagnostics.StackTrace, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.IdentityModel.Tokens.Jwt.5.5.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll</HintPath>
+    </Reference>
+    <Reference Include="System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" />
+    <Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net" />
+    <Reference Include="System.Net.Http.WebRequest" />
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Reflection.Metadata, Version=1.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Security" />
+    <Reference Include="System.Security.AccessControl, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.Cng, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.Cng.4.5.0\lib\net461\System.Security.Cryptography.Cng.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Security.Cryptography.Xml, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.Xml.4.5.0\lib\net461\System.Security.Cryptography.Xml.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Security.Permissions, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Permissions.4.5.0\lib\net461\System.Security.Permissions.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Security.Principal.Windows, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll</HintPath>
+    </Reference>
+    <Reference Include="System.ServiceModel" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Text.Encoding.CodePages, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Text.Encoding.CodePages.4.5.1\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Text.Encodings.Web, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Text.Encodings.Web.4.5.0\lib\netstandard2.0\System.Text.Encodings.Web.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Transactions" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System.Xml.XmlDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll</HintPath>
+      <Private>True</Private>
+      <Private>True</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Controllers\VersionController.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Startup.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="LinqToDB.Templates\DataAnnotations.ttinclude" />
+    <None Include="LinqToDB.Templates\DataModel.ttinclude" />
+    <None Include="LinqToDB.Templates\EditableObject.ttinclude" />
+    <None Include="LinqToDB.Templates\Humanizer.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Access.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Access.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.DB2.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.DB2.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Firebird.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Firebird.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Informix.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Informix.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.MySql.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.MySql.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Oracle.Managed.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Oracle.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Oracle.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Oracle.x64.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Oracle.x86.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.PostgreSQL.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.PostgreSQL.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SapHana.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SapHana.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlCe.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlCe.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SQLite.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SQLite.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlServer.SqlTypes.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlServer.SqlTypes.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlServer.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.SqlServer.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Sybase.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Sybase.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.Tools.ttinclude" />
+    <None Include="LinqToDB.Templates\LinqToDB.ttinclude" />
+    <None Include="LinqToDB.Templates\MultipleFiles.ttinclude" />
+    <None Include="LinqToDB.Templates\NotifyDataErrorInfo.ttinclude" />
+    <None Include="LinqToDB.Templates\NotifyPropertyChanged.ttinclude" />
+    <None Include="LinqToDB.Templates\ObsoleteAttributes.ttinclude" />
+    <None Include="LinqToDB.Templates\PluralizationService.ttinclude" />
+    <None Include="LinqToDB.Templates\README.md" />
+    <None Include="LinqToDB.Templates\T4Model.ttinclude" />
+    <None Include="LinqToDB.Templates\Validation.ttinclude" />
+    <Content Include="NLog.config">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <None Include="NLog.xsd">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="LinqToDB.Templates\CopyMe.Access.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.DB2.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.Firebird.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.Informix.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.MySql.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.Oracle.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.PostgreSQL.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.SapHana.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.SqlCe.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.SQLite.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.SqlServer.tt.txt" />
+    <Content Include="LinqToDB.Templates\CopyMe.Sybase.tt.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
+    <Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.4.4\build\EntityFramework.props'))" />
+    <Error Condition="!Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.4.4\build\EntityFramework.targets'))" />
+    <Error Condition="!Exists('..\packages\linq2db.SqlServer.2.6.4\build\linq2db.SqlServer.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\linq2db.SqlServer.2.6.4\build\linq2db.SqlServer.props'))" />
+    <Error Condition="!Exists('..\packages\linq2db.t4models.2.6.4\build\linq2db.t4models.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\linq2db.t4models.2.6.4\build\linq2db.t4models.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.AspNetCore.Razor.Design.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.AspNetCore.Razor.Design.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\build\Microsoft.CodeAnalysis.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.2\build\Microsoft.CodeAnalysis.Analyzers.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.DiaSymReader.Native.1.7.0\build\Microsoft.DiaSymReader.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.DiaSymReader.Native.1.7.0\build\Microsoft.DiaSymReader.Native.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets'))" />
+    <Error Condition="!Exists('..\packages\NUnit.3.12.0\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.12.0\build\NUnit.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets'))" />
+    <Error Condition="!Exists('..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.props'))" />
+    <Error Condition="!Exists('..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.targets'))" />
+  </Target>
+  <Import Project="..\packages\EntityFramework.6.4.4\build\EntityFramework.targets" Condition="Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" />
+  <Import Project="..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets" Condition="Exists('..\packages\Microsoft.Extensions.ApiDescription.Server.3.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets')" />
+  <Import Project="..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets" Condition="Exists('..\packages\Microsoft.AspNetCore.Mvc.Razor.Extensions.2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets')" />
+  <Import Project="..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.targets" Condition="Exists('..\packages\NSwag.AspNetCore.13.6.2\build\NSwag.AspNetCore.targets')" />
+</Project>
\ No newline at end of file
diff --git a/src/Version/packages.config b/src/Version/packages.config
new file mode 100644
index 0000000000000000000000000000000000000000..98e4db61cda19292530a244b9b3a4e032edda6c3
--- /dev/null
+++ b/src/Version/packages.config
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Aspose.Email" version="20.10.0" targetFramework="net461" />
+  <package id="Consul" version="0.7.2.6" targetFramework="net461" />
+  <package id="Coscine.ApiCommons" version="1.10.0" targetFramework="net461" />
+  <package id="Coscine.Configuration" version="1.5.0" targetFramework="net461" />
+  <package id="Coscine.Database" version="1.24.0" targetFramework="net461" />
+  <package id="Coscine.Logging" version="1.2.0" targetFramework="net461" />
+  <package id="EntityFramework" version="6.4.4" targetFramework="net461" />
+  <package id="linq2db" version="3.1.1" targetFramework="net461" />
+  <package id="linq2db.SqlServer" version="2.6.4" targetFramework="net461" />
+  <package id="linq2db.t4models" version="2.6.4" targetFramework="net461" />
+  <package id="LinqKit" version="1.1.17" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Antiforgery" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authentication" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authentication.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authentication.Core" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authentication.JwtBearer" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authorization" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Authorization.Policy" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Connections.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Cors" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Cryptography.Internal" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.DataProtection" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.DataProtection.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Diagnostics" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Diagnostics.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Hosting" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Hosting.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Hosting.Server.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Html.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Http" version="2.2.2" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Http.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Http.Extensions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Http.Features" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.HttpOverrides" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.JsonPatch" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Localization" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Analyzers" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.ApiExplorer" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Core" version="2.2.2" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Cors" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.DataAnnotations" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Formatters.Json" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Localization" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Razor" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.Razor.Extensions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.RazorPages" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.TagHelpers" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Mvc.ViewFeatures" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Razor" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Razor.Design" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Razor.Language" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Razor.Runtime" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.ResponseCaching.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Routing" version="2.2.2" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Routing.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Server.Kestrel" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Server.Kestrel.Core" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Server.Kestrel.Https" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" version="2.2.1" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.StaticFiles" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.AspNetCore.WebUtilities" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.CodeAnalysis.Analyzers" version="2.9.2" targetFramework="net461" />
+  <package id="Microsoft.CodeAnalysis.Common" version="3.0.0" targetFramework="net461" />
+  <package id="Microsoft.CodeAnalysis.CSharp" version="3.0.0" targetFramework="net461" />
+  <package id="Microsoft.CodeAnalysis.Razor" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.CSharp" version="4.5.0" targetFramework="net461" />
+  <package id="Microsoft.DiaSymReader.Native" version="1.7.0" targetFramework="net461" />
+  <package id="Microsoft.DotNet.PlatformAbstractions" version="2.1.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.ApiDescription.Server" version="3.0.0" targetFramework="net461" developmentDependency="true" />
+  <package id="Microsoft.Extensions.Caching.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Caching.Memory" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Configuration" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Configuration.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Configuration.Binder" version="2.2.4" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Configuration.EnvironmentVariables" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Configuration.FileExtensions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.DependencyInjection" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.DependencyModel" version="2.1.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.FileProviders.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.FileProviders.Composite" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.FileProviders.Embedded" version="1.0.1" targetFramework="net461" />
+  <package id="Microsoft.Extensions.FileProviders.Physical" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.FileSystemGlobbing" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Hosting.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Localization" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Localization.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Logging" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Logging.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.ObjectPool" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Options" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.Primitives" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Extensions.WebEncoders" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.IdentityModel.JsonWebTokens" version="5.5.0" targetFramework="net461" />
+  <package id="Microsoft.IdentityModel.Logging" version="5.5.0" targetFramework="net461" />
+  <package id="Microsoft.IdentityModel.Protocols" version="5.3.0" targetFramework="net461" />
+  <package id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="5.3.0" targetFramework="net461" />
+  <package id="Microsoft.IdentityModel.Tokens" version="5.5.0" targetFramework="net461" />
+  <package id="Microsoft.Net.Http.Headers" version="2.2.0" targetFramework="net461" />
+  <package id="Microsoft.Win32.Registry" version="4.5.0" targetFramework="net461" />
+  <package id="Namotion.Reflection" version="1.0.11" targetFramework="net461" />
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
+  <package id="Newtonsoft.Json.Bson" version="1.0.2" targetFramework="net461" />
+  <package id="NJsonSchema" version="10.1.23" targetFramework="net461" />
+  <package id="NLog" version="4.6.8" targetFramework="net461" />
+  <package id="NLog.Config" version="4.6.8" targetFramework="net461" />
+  <package id="NLog.Extensions.Logging" version="1.6.1" targetFramework="net461" />
+  <package id="NLog.Schema" version="4.6.8" targetFramework="net461" />
+  <package id="NLog.Web.AspNetCore" version="4.9.0" targetFramework="net461" />
+  <package id="NSwag.Annotations" version="13.6.2" targetFramework="net461" />
+  <package id="NSwag.AspNetCore" version="13.6.2" targetFramework="net461" />
+  <package id="NSwag.Core" version="13.6.2" targetFramework="net461" />
+  <package id="NSwag.Generation" version="13.6.2" targetFramework="net461" />
+  <package id="NSwag.Generation.AspNetCore" version="13.6.2" targetFramework="net461" />
+  <package id="NUnit" version="3.12.0" targetFramework="net461" />
+  <package id="System.AppContext" version="4.3.0" targetFramework="net461" />
+  <package id="System.Buffers" version="4.5.0" targetFramework="net461" />
+  <package id="System.Collections" version="4.3.0" targetFramework="net461" />
+  <package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />
+  <package id="System.ComponentModel.Annotations" version="4.5.0" targetFramework="net461" />
+  <package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" />
+  <package id="System.Diagnostics.DiagnosticSource" version="4.5.1" targetFramework="net461" />
+  <package id="System.Diagnostics.StackTrace" version="4.3.0" targetFramework="net461" />
+  <package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net461" />
+  <package id="System.IdentityModel.Tokens.Jwt" version="5.5.0" targetFramework="net461" />
+  <package id="System.IO" version="4.3.0" targetFramework="net461" />
+  <package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" />
+  <package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" />
+  <package id="System.IO.Pipelines" version="4.5.3" targetFramework="net461" />
+  <package id="System.Linq" version="4.3.0" targetFramework="net461" />
+  <package id="System.Memory" version="4.5.2" targetFramework="net461" />
+  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
+  <package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net461" />
+  <package id="System.Runtime" version="4.3.1" targetFramework="net461" />
+  <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
+  <package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net461" />
+  <package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net461" />
+  <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" />
+  <package id="System.Security.AccessControl" version="4.5.0" targetFramework="net461" />
+  <package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net461" />
+  <package id="System.Security.Cryptography.Cng" version="4.5.0" targetFramework="net461" />
+  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
+  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
+  <package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net461" />
+  <package id="System.Security.Cryptography.Xml" version="4.5.0" targetFramework="net461" />
+  <package id="System.Security.Permissions" version="4.5.0" targetFramework="net461" />
+  <package id="System.Security.Principal.Windows" version="4.5.1" targetFramework="net461" />
+  <package id="System.Text.Encoding.CodePages" version="4.5.1" targetFramework="net461" />
+  <package id="System.Text.Encodings.Web" version="4.5.0" targetFramework="net461" />
+  <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net461" />
+  <package id="System.Threading.Thread" version="4.3.0" targetFramework="net461" />
+  <package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net461" />
+  <package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net461" />
+</packages>
\ No newline at end of file