SlideShare a Scribd company logo
TUGA IT 2016
LISBON, PORTUGAL
THANK YOU TO OUR SPONSORS
THANK YOU TO OUR TEAM
ANDRÉ BATISTA ANDRÉ MELANCIA ANDRÉ VALA ANTÓNIO LOURENÇO BRUNO LOPES CLÁUDIO SILVA
NIKO NEUGEBAUER
RUI REISRICARDO CABRAL
NUNO CANCELO PAULO MATOS PEDRO SIMÕES
SANDRA MORGADO SANDRO PEREIRARUI BASTOS
NUNO ÁRIAS SILVA
Level Up Your Biml:
Best Practices and Coding Techniques
Cathrine Wilhelmsen · TUGA IT · May 21st 2016
Session Description
Is your Biml solution starting to remind you of a bowl of tangled spaghetti code? Good! That
means you are solving real problems while saving a lot of time. The next step is to make sure
that your solution does not grow too complex and confusing – you do not want to waste all
that saved time on future maintenance!
Attend this session for an overview of Biml best practices and coding techniques. Step by step,
we will simplify and enhance our solution. Learn how to centralize and reuse code with
Include files and the CallBimlScript method. Make your code easier to read and write by
utilizing LINQ (Language-Integrated Queries). Share code between files by using Annotations
and ObjectTags. And finally, if standard Biml is not enough to solve your problems, you can
create your own C# helper classes and extension methods to implement custom logic.
Start improving your code today and level up your Biml in no time!
You…
…?
Know basic Biml and BimlScript
Completed BimlScript.com lessons
Have created a staging environment
Next 70 minutes…
…?
Code Management
Practical Biml Coding
C# Classes and Methods
Cathrine Wilhelmsen
@cathrinew
cathrinewilhelmsen.net
Data Warehouse Architect
Business Intelligence Developer
Biml Tools
What do you need?
BIDS Helper
Free open-source add-in for Visual Studio
60+ features for SSIS, SSAS and SSRS
Includes basic Biml package generator
bidshelper.codeplex.com
…or you can use the new Biml tools
BimlExpress
Free add-in for Visual Studio
Code editor with syntax highlighting and Biml Intellisense
More frequent updates than BIDS Helper
varigence.com/bimlexpress
BimlOnline
Free browser-based Biml editor
Code editor with Biml and C# Intellisense
Reverse-engineer from SSIS to Biml
bimlonline.com
BimlStudio
Licensed full-featured development environment for Biml
Visual designer and metadata modeling
Full-stack automation and transformers
varigence.com/bimlstudio
Comparing Biml Tools
Free
Biml Intellisense
"Black Box"
Free
Full Intellisense
Logical View
Licensed
Full IDE
Preview BimlScript
Biml and
BimlScript
Biml
Business Intelligence Markup Language
XML Language – just text
Easy to read and write – but can be verbose
You can use any tool to generate the Biml for you…
(Text editor macros, Excel, PowerShell, T-SQL ++)
BimlScript
…but use BimlScript :)
Extend Biml with integrated C# (or VB) code blocks
Allows you to generate, control and manipulate Biml
Import metadata and quickly script entire solutions
BimlScript Code Nuggets
<# … #> Control Nuggets (Control logic)
<#= … #> Text Nuggets (Returns string)
<#@ … #> Directives (Compiler instructions)
<#+ … #> Class Nuggets (Create C# classes)
How does it work?
Yes, but how does it work?
Yes, but how does it actually work?
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<# foreach (var table in RootNode.Tables) { #>
<Package Name="Load_<#=table.Name#>"></Package>
<# } #>
</Packages>
</Biml>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<Package Name="Load_Customer"/>
<Package Name="Load_Product"/>
<Package Name="Load_Sales"/>
</Packages>
</Biml>
Biml and BimlScript
Flat XML
"Just text"
Generate, control and
manipulate Biml with C#
Code Management
Don't Repeat Yourself
Move common code to separate files
Centralize and reuse in many projects
Update code once for all projects
1. Include files
2. CallBimlScript with Parameters
3. Tiered Biml files
Include Files
Include common code in multiple files and projects
Can include many file types: .biml .txt .sql .cs
Use the include directive
<#@ include file="CommonCode.biml" #>
The directive will be replaced by the included file
Works like an automated Copy & Paste
Include Files
Include Files
Include Files
CallBimlScript with Parameters
Works like a parameterized include (or stored procedure)
File to be called (callee) specifies input parameters it accepts
<#@ property name="Parameter" type="String" #>
File that calls (caller) passes input parameters
<#=CallBimlScript("CommonCode.biml", Parameter)#>
CallBimlScript with Parameters
CallBimlScript with Parameters
CallBimlScript with Parameters
CallBimlScript with Parameters
CallBimlScript with Parameters
Tiered Biml Files
Split Biml code in multiple files and use the template directive:
<#@ template tier="1" #>
Compile Biml from lowest to highest tier to:
• Solve logical dependencies
• Simulate manual workflows
For each tier, objects are added to the RootNode
Higher tiers can use objects from lower tiers
What is this RootNode?
When working with flat Biml,
the <Biml> root element contains
collections of root objects:
<Biml>
<Connections>...</Connections>
<Databases>...</Databases>
<Schemas>...</Schemas>
<Tables>...</Tables>
<Projects>...</Projects>
<Packages>...</Packages>
</Biml>
When working with BimlScript,
the RootNode contains collections of
root objects:
=
How do I query the RootNode?
Query the RootNode to loop over collections:
<# foreach (var table in RootNode.Tables) { #>
Query the RootNode to get specific objects:
<#=RootNode.Tables["Product"].Schema#>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
<#@ template tier="1" #>
<Connections>...</Connections>
<#@ template tier="2" #>
<Packages>...</Packages>
<#@ template tier="3" #>
<Package>...</Package>
Inside the Black Box: Tiered Biml Files
How do you use Tiered Biml files?
1. Create Biml files with specified tiers
2. Select all the tiered Biml files
3. Right-click and click Generate SSIS Packages
1
2
3
How does this
actually work?
Debugging
Debugging Biml
BimlExpress is a "black box":
• You can only see the generated SSIS packages
• It is not possible to see the compiled Biml first
Add a high-tier helper file to save compiled Biml to file
• Check Biml For Errors saves compiled Biml
without generating packages
SaveFlatBimlToFile.biml
Add the helper file to your project…
<#@ template tier="999" #>
<# System.IO.File.WriteAllText(
@"C:BimlFlatBiml.xml",
RootNode.GetBiml()
); #>
SaveFlatBimlToFile.biml
…with a high tier so it is executed as the last step
<#@ template tier="999" #>
<# System.IO.File.WriteAllText(
@"C:BimlFlatBiml.xml",
RootNode.GetBiml()
); #>
SaveFlatBimlToFile.biml
It creates a file…
<#@ template tier="999" #>
<# System.IO.File.WriteAllText(
@"C:BimlFlatBiml.xml",
RootNode.GetBiml()
); #>
SaveFlatBimlToFile.biml
…at the specified path…
<#@ template tier="999" #>
<# System.IO.File.WriteAllText(
@"C:BimlFlatBiml.xml",
RootNode.GetBiml()
); #>
SaveFlatBimlToFile.biml
…with all the Biml for all the objects in RootNode :)
<#@ template tier="999" #>
<# System.IO.File.WriteAllText(
@"C:BimlFlatBiml.xml",
RootNode.GetBiml()
); #>
How do you use this helper file?
1. Create the helper file
2. Select all the Biml files and the helper file
3. Right-click and click Check Biml For Errors
1
2
3
How is this
helper file used?
Annotations and
ObjectTags
Annotations and ObjectTags
Biml Annotations != SSIS Annotations
Annotations are string/string Key/Value pairs
ObjectTags are string/object Key/Value pairs
Use Annotations and ObjectTags to pass code
between Biml files
Annotations
Create annotations:
<OleDbConnection Name="Destination" ConnectionString="…">
<Annotations>
<Annotation Tag="Schema">AW2014</Annotation>
</Annotations>
</OleDbConnection>
Use annotations:
<# var destinationSchema =
RootNode.OleDbConnections["Destination"].GetTag("Schema"); #>
ObjectTags
Create ObjectTags:
<#
RootNode.OleDbConnections["Destination"].ObjectTag["TableFilter"] =
new List<string> {"Product","ProductSubcategory","ProductCategory"};
#>
Use ObjectTags:
<#
var TableFilter = (List<string>)
RootNode.OleDbConnections["Destination"].ObjectTag["TableFilter"];
#>
LINQ
LINQ (Language-Integrated Query)
One language to query:
SQL Server Databases
XML Documents
Datasets
Collections
Two ways to write queries:
SQL-like Syntax
Extension Methods
LINQ Extension Methods
..and many, many more!
Sort
OrderBy, ThenBy
Filter
Where, OfType
Group
GroupBy
Aggregate
Count, Sum
Check Collections
All, Any, Contains
Get Elements
First, Last, ElementAt
Project Collections
Select, SelectMany
LINQ Extension Methods
var numConnections = RootNode.Connections.Count()
foreach (var table in RootNode.Tables.Where(…))
if (RootNode.Packages.Any(…))
LINQ and Lambda expressions
Use lambda expressions to filter or specify values:
.Where(table => table.Schema.Name == "Production")
.OrderBy(table => table.Name)
LINQ and Lambda expressions
For each element in the collection…
.Where(table => table.Schema.Name == "Production")
.OrderBy(table => table.Name)
LINQ and Lambda expressions
…evaluate a criteria or get a value:
.Where(table => table.Schema.Name == "Production")
.OrderBy(table => table.Name)
LINQ: Filter collections
Where()
Returns the filtered collection with all elements that meet the criteria
RootNode.Tables.Where(t => t.Schema.Name == "Production")
OfType()
Returns the filtered collection with all elements of the specified type
RootNode.Connections.OfType<AstExcelOleDbConnectionNode>()
LINQ: Sort collections
OrderBy()
Returns the collection sorted by key…
RootNode.Tables.OrderBy(t => t.Name)
ThenBy()
…then sorted by secondary key
RootNode.Tables.OrderBy(t => t.Schema.Name)
.ThenBy(t => t.Name)
LINQ: Sort collections
OrderByDescending()
Returns the collection sorted by key…
RootNode.Tables.OrderByDescending(t => t.Name)
ThenByDescending()
…then sorted by secondary key
RootNode.Tables.OrderBy(t => t.Schema.Name)
.ThenByDescending(t => t.Name)
LINQ: Sort collections
Reverse()
Returns the collection sorted in reverse order
RootNode.Tables.Reverse()
LINQ: Group collections
GroupBy()
Returns a collection of key-value pairs where each value is a new collection
RootNode.Tables.GroupBy(t => t.Schema.Name)
LINQ: Aggregate collections
Count()
Returns the number of elements in the collection
RootNode.Tables.Count()
RootNode.Tables.Count(t => t.Schema.Name == "Production")
LINQ: Aggregate collections
Sum()
Returns the sum of the (numeric) values in the collection
RootNode.Tables.Sum(t => t.Columns.Count)
Average()
Returns the average value of the (numeric) values in the collection
RootNode.Tables.Average(t => t.Columns.Count)
LINQ: Aggregate collections
Min()
Returns the minimum value of the (numeric) values in the collection
RootNode.Tables.Min(t => t.Columns.Count)
Max()
Returns the maximum value of the (numeric) values in the collection
RootNode.Tables.Max(t => t.Columns.Count)
LINQ: Check collections
All()
Returns true if all elements in the collection meet the criteria
RootNode.Databases.All(d => d.Name.StartsWith("A"))
Any()
Returns true if any element in the collection meets the criteria
RootNode.Databases.Any(d => d.Name.Contains("DW"))
LINQ: Check collections
Contains()
Returns true if collection contains element
RootNode.Databases.Contains(AdventureWorks2014)
LINQ: Get elements
First()
Returns the first element in the collection (that meets the criteria)
RootNode.Tables.First()
RootNode.Tables.First(t => t.Schema.Name == "Production")
FirstOrDefault()
Returns the first element in the collection or default value (that meets the criteria)
RootNode.Tables.FirstOrDefault()
RootNode.Tables.FirstOrDefault(t => t.Schema.Name == "Production")
LINQ: Get elements
Last()
Returns the last element in the collection (that meets the criteria)
RootNode.Tables.Last()
RootNode.Tables.Last(t => t.Schema.Name == "Production")
LastOrDefault()
Returns the last element in the collection or default value (that meets the criteria)
RootNode.Tables.LastOrDefault()
RootNode.Tables.LastOrDefault(t => t.Schema.Name == "Production")
LINQ: Get elements
ElementAt()
Returns the element in the collection at the specified index
RootNode.Tables.ElementAt(42)
ElementAtOrDefault()
Returns the element in the collection or default value at the specified index
RootNode.Tables.ElementAtOrDefault(42)
LINQ: Project collections
Select()
Creates a new collection from one collection
A list of table names:
RootNode.Tables.Select(t => t.Name)
A list of table and schema names:
RootNode.Tables.Select(t => new {t.Name, t.Schema.Name})
LINQ: Project collections
SelectMany()
Creates a new collection from many collections and merges the collections
A list of all columns from all tables:
RootNode.Tables.SelectMany(t => t.Columns)
How is LINQ used
in Biml projects?
Classes and
Methods
C# Classes and Methods
BimlScript and LINQ not enough?
Need to reuse C# code?
Create your own classes and methods!
C# Classes and Methods: From this…
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
if (node.GetTag(tag) != "") {
return true;
} else {
return false;
}
}
}
C# Classes and Methods: …to this
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
if (node.GetTag(tag) != "") {
return true;
}
return false;
}
}
C# Classes and Methods: …to this
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
C# Classes and Methods: …to this
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "");
}
}
Where do you put your C# code?
Inline code nuggets
Included Biml files with code nuggets
Reference code files
C# Classes and Methods: Inline
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
<#+
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
#>
C# Classes and Methods: Included Files
<#@ include file="HelperClass.biml" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
<#+
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
#>
C# Classes and Methods: Code Files
<#@ code file="HelperClass.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
Extension Methods
Extension Methods
"Make it look like the method belongs to
an object instead of a helper class"
Extension Methods: From this…
<#@ code file="HelperClass.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
public static class HelperClass {
public static bool AnnotationTagExists(AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
Extension Methods: …to this
<#@ code file="HelperClass.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
public static class HelperClass {
public static bool AnnotationTagExists(this AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
Extension Methods: …to this
<#@ code file="HelperClass.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables) { #>
<# if (table.AnnotationTagExists("SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
public static class HelperClass {
public static bool AnnotationTagExists(this AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
Extension Methods: …to this :)
<#@ code file="HelperClass.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<# foreach (var table in RootNode.Tables.Where(t =>
t.AnnotationTagExists("SourceSchema")) { #>
...
<# } #>
<# } #>
</Biml>
public static class HelperClass {
public static bool AnnotationTagExists(this AstNode node, string tag) {
return (node.GetTag(tag) != "") ? true : false;
}
}
Get things done
Start small
Start simple
Start with ugly code
Keep going
Expand
Improve
Deliver often
Level Up Your Biml: Best Practices and Coding Techniques (TUGA IT 2016)
@cathrinew
cathrinewilhelmsen.net
linkedin.com/in/cathrinewilhelmsen
contact@cathrinewilhelmsen.net
slideshare.net/cathrinewilhelmsen
Biml resources and references:
cathrinewilhelmsen.net/biml
THANK YOU TO OUR SPONSORS

More Related Content

PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Oslo)
PDF
Biml for Beginners: Speed up your SSIS development (Malta Microsoft Data Plat...
PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Sacrame...
PDF
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Ex...
PDF
Don't Repeat Yourself - An Introduction to Agile SSIS Development (24 Hours o...
PDF
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
PDF
Level Up Your Biml: Best Practices and Coding Techniques (NTK 2016)
PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Iceland)
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Oslo)
Biml for Beginners: Speed up your SSIS development (Malta Microsoft Data Plat...
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Sacrame...
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Ex...
Don't Repeat Yourself - An Introduction to Agile SSIS Development (24 Hours o...
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Level Up Your Biml: Best Practices and Coding Techniques (NTK 2016)
Biml for Beginners: Speed up your SSIS development (SQLSaturday Iceland)

What's hot (20)

PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Chicago)
PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Minnesota)
PDF
Don't Repeat Yourself - Agile SSIS Development with Biml and BimlScript (SQL ...
PDF
Biml for Beginners: Speed up your SSIS development (SQLBits XV)
PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Denver)
PDF
Biml Academy 2 - Lesson 5: Importing source metadata into Biml
PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Vancouver)
PDF
S.M.A.R.T. Biml - Standardize, Model, Automate, Reuse and Transform (SQLSatur...
PDF
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Go...
PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Vienna)
PDF
Upgrading from SSIS Package Deployment to Project Deployment (SQLSaturday Den...
PDF
Tools and Tips: From Accidental to Efficient Data Warehouse Developer (SQLSat...
PDF
Biml for Beginners: Speed up your SSIS development (SQL PASS Edmonton )
PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Tallinn)
PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLBits 2018)
PDF
Biml for Beginners: Script and Automate SSIS development (SQLSaturday Chicago)
PDF
Biml for Beginners: Script and Automate SSIS development (Capital Area SQL Se...
PDF
Biml for Beginners: Speed up your SSIS development (SQLSaturday Nashville)
PDF
Biml for Beginners: Script and Automate SSIS development (Malibu SQL Server U...
PDF
Marty, You're Just Not Thinking Fourth Dimensionally
Biml for Beginners: Speed up your SSIS development (SQLSaturday Chicago)
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Minnesota)
Don't Repeat Yourself - Agile SSIS Development with Biml and BimlScript (SQL ...
Biml for Beginners: Speed up your SSIS development (SQLBits XV)
Level Up Your Biml: Best Practices and Coding Techniques (SQLSaturday Denver)
Biml Academy 2 - Lesson 5: Importing source metadata into Biml
Biml for Beginners: Speed up your SSIS development (SQLSaturday Vancouver)
S.M.A.R.T. Biml - Standardize, Model, Automate, Reuse and Transform (SQLSatur...
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Go...
Biml for Beginners: Speed up your SSIS development (SQLSaturday Vienna)
Upgrading from SSIS Package Deployment to Project Deployment (SQLSaturday Den...
Tools and Tips: From Accidental to Efficient Data Warehouse Developer (SQLSat...
Biml for Beginners: Speed up your SSIS development (SQL PASS Edmonton )
Biml for Beginners: Speed up your SSIS development (SQLSaturday Tallinn)
Level Up Your Biml: Best Practices and Coding Techniques (SQLBits 2018)
Biml for Beginners: Script and Automate SSIS development (SQLSaturday Chicago)
Biml for Beginners: Script and Automate SSIS development (Capital Area SQL Se...
Biml for Beginners: Speed up your SSIS development (SQLSaturday Nashville)
Biml for Beginners: Script and Automate SSIS development (Malibu SQL Server U...
Marty, You're Just Not Thinking Fourth Dimensionally
Ad

Similar to Level Up Your Biml: Best Practices and Coding Techniques (TUGA IT 2016) (15)

PDF
Level Up Your Biml: Best Practices and Coding Techniques (SQLDay 2018)
PDF
Biml for Beginners: Script and Automate SSIS development (24 Hours of PASS: S...
PDF
Level Up Your Biml: Best Practices and Coding Techniques (PASS Summit 2018)
PDF
CI/CD Templates: Continuous Delivery of ML-Enabled Data Pipelines on Databricks
PDF
Lecture 1
PPT
Admin2009 raven justifying
PPTX
Making your user happy – how to create a perfect profile
PDF
Case Study: The Value of Partnership during DITA Conversion
TXT
!!Readme
PDF
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
PDF
C 10 Pocket Reference Instant Help For C 10 Programmers First Early Release 1...
KEY
Running an Open-Source CodeIgniter project
KEY
CICON2010: Phil Sturgeon - Running an Open-Source CodeIgniter project
PPT
Ms vb
PDF
Ad505 dev blast
Level Up Your Biml: Best Practices and Coding Techniques (SQLDay 2018)
Biml for Beginners: Script and Automate SSIS development (24 Hours of PASS: S...
Level Up Your Biml: Best Practices and Coding Techniques (PASS Summit 2018)
CI/CD Templates: Continuous Delivery of ML-Enabled Data Pipelines on Databricks
Lecture 1
Admin2009 raven justifying
Making your user happy – how to create a perfect profile
Case Study: The Value of Partnership during DITA Conversion
!!Readme
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
C 10 Pocket Reference Instant Help For C 10 Programmers First Early Release 1...
Running an Open-Source CodeIgniter project
CICON2010: Phil Sturgeon - Running an Open-Source CodeIgniter project
Ms vb
Ad505 dev blast
Ad

More from Cathrine Wilhelmsen (20)

PDF
Fra utvikler til arkitekt: Skap din egen karrierevei ved å utvikle din person...
PDF
One Year in Fabric: Lessons Learned from Implementing Real-World Projects (PA...
PDF
Data Factory in Microsoft Fabric (MsBIP #82)
PDF
Getting Started: Data Factory in Microsoft Fabric (Microsoft Fabric Community...
PDF
Choosing Between Microsoft Fabric, Azure Synapse Analytics and Azure Data Fac...
PDF
Website Analytics in My Pocket using Microsoft Fabric (SQLBits 2024)
PDF
Data Integration using Data Factory in Microsoft Fabric (ESPC Microsoft Fabri...
PDF
Choosing between Fabric, Synapse and Databricks (Data Left Unattended 2023)
PDF
Data Integration with Data Factory (Microsoft Fabric Day Oslo 2023)
PDF
The Battle of the Data Transformation Tools (PASS Data Community Summit 2023)
PDF
Visually Transform Data in Azure Data Factory or Azure Synapse Analytics (PAS...
PDF
Building an End-to-End Solution in Microsoft Fabric: From Dataverse to Power ...
PDF
Website Analytics in my Pocket using Microsoft Fabric (AdaCon 2023)
PDF
Choosing Between Microsoft Fabric, Azure Synapse Analytics and Azure Data Fac...
PDF
Stressed, Depressed, or Burned Out? The Warning Signs You Shouldn't Ignore (D...
PDF
Stressed, Depressed, or Burned Out? The Warning Signs You Shouldn't Ignore (S...
PDF
"I can't keep up!" - Turning Discomfort into Personal Growth in a Fast-Paced ...
PDF
Lessons Learned: Implementing Azure Synapse Analytics in a Rapidly-Changing S...
PDF
6 Tips for Building Confidence as a Public Speaker (SQLBits 2022)
PDF
Lessons Learned: Understanding Pipeline Pricing in Azure Data Factory and Azu...
Fra utvikler til arkitekt: Skap din egen karrierevei ved å utvikle din person...
One Year in Fabric: Lessons Learned from Implementing Real-World Projects (PA...
Data Factory in Microsoft Fabric (MsBIP #82)
Getting Started: Data Factory in Microsoft Fabric (Microsoft Fabric Community...
Choosing Between Microsoft Fabric, Azure Synapse Analytics and Azure Data Fac...
Website Analytics in My Pocket using Microsoft Fabric (SQLBits 2024)
Data Integration using Data Factory in Microsoft Fabric (ESPC Microsoft Fabri...
Choosing between Fabric, Synapse and Databricks (Data Left Unattended 2023)
Data Integration with Data Factory (Microsoft Fabric Day Oslo 2023)
The Battle of the Data Transformation Tools (PASS Data Community Summit 2023)
Visually Transform Data in Azure Data Factory or Azure Synapse Analytics (PAS...
Building an End-to-End Solution in Microsoft Fabric: From Dataverse to Power ...
Website Analytics in my Pocket using Microsoft Fabric (AdaCon 2023)
Choosing Between Microsoft Fabric, Azure Synapse Analytics and Azure Data Fac...
Stressed, Depressed, or Burned Out? The Warning Signs You Shouldn't Ignore (D...
Stressed, Depressed, or Burned Out? The Warning Signs You Shouldn't Ignore (S...
"I can't keep up!" - Turning Discomfort into Personal Growth in a Fast-Paced ...
Lessons Learned: Implementing Azure Synapse Analytics in a Rapidly-Changing S...
6 Tips for Building Confidence as a Public Speaker (SQLBits 2022)
Lessons Learned: Understanding Pipeline Pricing in Azure Data Factory and Azu...

Recently uploaded (20)

PPTX
Global journeys: estimating international migration
PDF
BF and FI - Blockchain, fintech and Financial Innovation Lesson 2.pdf
PPTX
Database Infoormation System (DBIS).pptx
PPTX
STUDY DESIGN details- Lt Col Maksud (21).pptx
PPTX
Supervised vs unsupervised machine learning algorithms
PPTX
Introduction to Firewall Analytics - Interfirewall and Transfirewall.pptx
PPTX
Computer network topology notes for revision
PPT
Quality review (1)_presentation of this 21
PPTX
Introduction-to-Cloud-ComputingFinal.pptx
PDF
Mega Projects Data Mega Projects Data
PPTX
Business Acumen Training GuidePresentation.pptx
PPTX
Data_Analytics_and_PowerBI_Presentation.pptx
PDF
Introduction to Business Data Analytics.
PPT
Chapter 3 METAL JOINING.pptnnnnnnnnnnnnn
PPTX
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
PPTX
CEE 2 REPORT G7.pptxbdbshjdgsgjgsjfiuhsd
PDF
Clinical guidelines as a resource for EBP(1).pdf
PPTX
Business Ppt On Nestle.pptx huunnnhhgfvu
PPTX
iec ppt-1 pptx icmr ppt on rehabilitation.pptx
PPTX
Introduction to Knowledge Engineering Part 1
Global journeys: estimating international migration
BF and FI - Blockchain, fintech and Financial Innovation Lesson 2.pdf
Database Infoormation System (DBIS).pptx
STUDY DESIGN details- Lt Col Maksud (21).pptx
Supervised vs unsupervised machine learning algorithms
Introduction to Firewall Analytics - Interfirewall and Transfirewall.pptx
Computer network topology notes for revision
Quality review (1)_presentation of this 21
Introduction-to-Cloud-ComputingFinal.pptx
Mega Projects Data Mega Projects Data
Business Acumen Training GuidePresentation.pptx
Data_Analytics_and_PowerBI_Presentation.pptx
Introduction to Business Data Analytics.
Chapter 3 METAL JOINING.pptnnnnnnnnnnnnn
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
CEE 2 REPORT G7.pptxbdbshjdgsgjgsjfiuhsd
Clinical guidelines as a resource for EBP(1).pdf
Business Ppt On Nestle.pptx huunnnhhgfvu
iec ppt-1 pptx icmr ppt on rehabilitation.pptx
Introduction to Knowledge Engineering Part 1

Level Up Your Biml: Best Practices and Coding Techniques (TUGA IT 2016)

  • 2. THANK YOU TO OUR SPONSORS
  • 3. THANK YOU TO OUR TEAM ANDRÉ BATISTA ANDRÉ MELANCIA ANDRÉ VALA ANTÓNIO LOURENÇO BRUNO LOPES CLÁUDIO SILVA NIKO NEUGEBAUER RUI REISRICARDO CABRAL NUNO CANCELO PAULO MATOS PEDRO SIMÕES SANDRA MORGADO SANDRO PEREIRARUI BASTOS NUNO ÁRIAS SILVA
  • 4. Level Up Your Biml: Best Practices and Coding Techniques Cathrine Wilhelmsen · TUGA IT · May 21st 2016
  • 5. Session Description Is your Biml solution starting to remind you of a bowl of tangled spaghetti code? Good! That means you are solving real problems while saving a lot of time. The next step is to make sure that your solution does not grow too complex and confusing – you do not want to waste all that saved time on future maintenance! Attend this session for an overview of Biml best practices and coding techniques. Step by step, we will simplify and enhance our solution. Learn how to centralize and reuse code with Include files and the CallBimlScript method. Make your code easier to read and write by utilizing LINQ (Language-Integrated Queries). Share code between files by using Annotations and ObjectTags. And finally, if standard Biml is not enough to solve your problems, you can create your own C# helper classes and extension methods to implement custom logic. Start improving your code today and level up your Biml in no time!
  • 6. You… …? Know basic Biml and BimlScript Completed BimlScript.com lessons Have created a staging environment
  • 7. Next 70 minutes… …? Code Management Practical Biml Coding C# Classes and Methods
  • 10. What do you need?
  • 11. BIDS Helper Free open-source add-in for Visual Studio 60+ features for SSIS, SSAS and SSRS Includes basic Biml package generator bidshelper.codeplex.com
  • 12. …or you can use the new Biml tools
  • 13. BimlExpress Free add-in for Visual Studio Code editor with syntax highlighting and Biml Intellisense More frequent updates than BIDS Helper varigence.com/bimlexpress
  • 14. BimlOnline Free browser-based Biml editor Code editor with Biml and C# Intellisense Reverse-engineer from SSIS to Biml bimlonline.com
  • 15. BimlStudio Licensed full-featured development environment for Biml Visual designer and metadata modeling Full-stack automation and transformers varigence.com/bimlstudio
  • 16. Comparing Biml Tools Free Biml Intellisense "Black Box" Free Full Intellisense Logical View Licensed Full IDE Preview BimlScript
  • 18. Biml Business Intelligence Markup Language XML Language – just text Easy to read and write – but can be verbose You can use any tool to generate the Biml for you… (Text editor macros, Excel, PowerShell, T-SQL ++)
  • 19. BimlScript …but use BimlScript :) Extend Biml with integrated C# (or VB) code blocks Allows you to generate, control and manipulate Biml Import metadata and quickly script entire solutions
  • 20. BimlScript Code Nuggets <# … #> Control Nuggets (Control logic) <#= … #> Text Nuggets (Returns string) <#@ … #> Directives (Compiler instructions) <#+ … #> Class Nuggets (Create C# classes)
  • 21. How does it work?
  • 22. Yes, but how does it work?
  • 23. Yes, but how does it actually work? <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Packages> <# foreach (var table in RootNode.Tables) { #> <Package Name="Load_<#=table.Name#>"></Package> <# } #> </Packages> </Biml> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Packages> <Package Name="Load_Customer"/> <Package Name="Load_Product"/> <Package Name="Load_Sales"/> </Packages> </Biml>
  • 24. Biml and BimlScript Flat XML "Just text" Generate, control and manipulate Biml with C#
  • 26. Don't Repeat Yourself Move common code to separate files Centralize and reuse in many projects Update code once for all projects 1. Include files 2. CallBimlScript with Parameters 3. Tiered Biml files
  • 27. Include Files Include common code in multiple files and projects Can include many file types: .biml .txt .sql .cs Use the include directive <#@ include file="CommonCode.biml" #> The directive will be replaced by the included file Works like an automated Copy & Paste
  • 31. CallBimlScript with Parameters Works like a parameterized include (or stored procedure) File to be called (callee) specifies input parameters it accepts <#@ property name="Parameter" type="String" #> File that calls (caller) passes input parameters <#=CallBimlScript("CommonCode.biml", Parameter)#>
  • 37. Tiered Biml Files Split Biml code in multiple files and use the template directive: <#@ template tier="1" #> Compile Biml from lowest to highest tier to: • Solve logical dependencies • Simulate manual workflows For each tier, objects are added to the RootNode Higher tiers can use objects from lower tiers
  • 38. What is this RootNode? When working with flat Biml, the <Biml> root element contains collections of root objects: <Biml> <Connections>...</Connections> <Databases>...</Databases> <Schemas>...</Schemas> <Tables>...</Tables> <Projects>...</Projects> <Packages>...</Packages> </Biml> When working with BimlScript, the RootNode contains collections of root objects: =
  • 39. How do I query the RootNode? Query the RootNode to loop over collections: <# foreach (var table in RootNode.Tables) { #> Query the RootNode to get specific objects: <#=RootNode.Tables["Product"].Schema#>
  • 40. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 41. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 42. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 43. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 44. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 45. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 46. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 47. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 48. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 49. Inside the Black Box: Tiered Biml Files <#@ template tier="1" #> <Connections>...</Connections> <#@ template tier="2" #> <Packages>...</Packages> <#@ template tier="3" #> <Package>...</Package>
  • 50. Inside the Black Box: Tiered Biml Files
  • 51. How do you use Tiered Biml files? 1. Create Biml files with specified tiers 2. Select all the tiered Biml files 3. Right-click and click Generate SSIS Packages 1 2 3
  • 54. Debugging Biml BimlExpress is a "black box": • You can only see the generated SSIS packages • It is not possible to see the compiled Biml first Add a high-tier helper file to save compiled Biml to file • Check Biml For Errors saves compiled Biml without generating packages
  • 55. SaveFlatBimlToFile.biml Add the helper file to your project… <#@ template tier="999" #> <# System.IO.File.WriteAllText( @"C:BimlFlatBiml.xml", RootNode.GetBiml() ); #>
  • 56. SaveFlatBimlToFile.biml …with a high tier so it is executed as the last step <#@ template tier="999" #> <# System.IO.File.WriteAllText( @"C:BimlFlatBiml.xml", RootNode.GetBiml() ); #>
  • 57. SaveFlatBimlToFile.biml It creates a file… <#@ template tier="999" #> <# System.IO.File.WriteAllText( @"C:BimlFlatBiml.xml", RootNode.GetBiml() ); #>
  • 58. SaveFlatBimlToFile.biml …at the specified path… <#@ template tier="999" #> <# System.IO.File.WriteAllText( @"C:BimlFlatBiml.xml", RootNode.GetBiml() ); #>
  • 59. SaveFlatBimlToFile.biml …with all the Biml for all the objects in RootNode :) <#@ template tier="999" #> <# System.IO.File.WriteAllText( @"C:BimlFlatBiml.xml", RootNode.GetBiml() ); #>
  • 60. How do you use this helper file? 1. Create the helper file 2. Select all the Biml files and the helper file 3. Right-click and click Check Biml For Errors 1 2 3
  • 61. How is this helper file used?
  • 63. Annotations and ObjectTags Biml Annotations != SSIS Annotations Annotations are string/string Key/Value pairs ObjectTags are string/object Key/Value pairs Use Annotations and ObjectTags to pass code between Biml files
  • 64. Annotations Create annotations: <OleDbConnection Name="Destination" ConnectionString="…"> <Annotations> <Annotation Tag="Schema">AW2014</Annotation> </Annotations> </OleDbConnection> Use annotations: <# var destinationSchema = RootNode.OleDbConnections["Destination"].GetTag("Schema"); #>
  • 65. ObjectTags Create ObjectTags: <# RootNode.OleDbConnections["Destination"].ObjectTag["TableFilter"] = new List<string> {"Product","ProductSubcategory","ProductCategory"}; #> Use ObjectTags: <# var TableFilter = (List<string>) RootNode.OleDbConnections["Destination"].ObjectTag["TableFilter"]; #>
  • 66. LINQ
  • 67. LINQ (Language-Integrated Query) One language to query: SQL Server Databases XML Documents Datasets Collections Two ways to write queries: SQL-like Syntax Extension Methods
  • 68. LINQ Extension Methods ..and many, many more! Sort OrderBy, ThenBy Filter Where, OfType Group GroupBy Aggregate Count, Sum Check Collections All, Any, Contains Get Elements First, Last, ElementAt Project Collections Select, SelectMany
  • 69. LINQ Extension Methods var numConnections = RootNode.Connections.Count() foreach (var table in RootNode.Tables.Where(…)) if (RootNode.Packages.Any(…))
  • 70. LINQ and Lambda expressions Use lambda expressions to filter or specify values: .Where(table => table.Schema.Name == "Production") .OrderBy(table => table.Name)
  • 71. LINQ and Lambda expressions For each element in the collection… .Where(table => table.Schema.Name == "Production") .OrderBy(table => table.Name)
  • 72. LINQ and Lambda expressions …evaluate a criteria or get a value: .Where(table => table.Schema.Name == "Production") .OrderBy(table => table.Name)
  • 73. LINQ: Filter collections Where() Returns the filtered collection with all elements that meet the criteria RootNode.Tables.Where(t => t.Schema.Name == "Production") OfType() Returns the filtered collection with all elements of the specified type RootNode.Connections.OfType<AstExcelOleDbConnectionNode>()
  • 74. LINQ: Sort collections OrderBy() Returns the collection sorted by key… RootNode.Tables.OrderBy(t => t.Name) ThenBy() …then sorted by secondary key RootNode.Tables.OrderBy(t => t.Schema.Name) .ThenBy(t => t.Name)
  • 75. LINQ: Sort collections OrderByDescending() Returns the collection sorted by key… RootNode.Tables.OrderByDescending(t => t.Name) ThenByDescending() …then sorted by secondary key RootNode.Tables.OrderBy(t => t.Schema.Name) .ThenByDescending(t => t.Name)
  • 76. LINQ: Sort collections Reverse() Returns the collection sorted in reverse order RootNode.Tables.Reverse()
  • 77. LINQ: Group collections GroupBy() Returns a collection of key-value pairs where each value is a new collection RootNode.Tables.GroupBy(t => t.Schema.Name)
  • 78. LINQ: Aggregate collections Count() Returns the number of elements in the collection RootNode.Tables.Count() RootNode.Tables.Count(t => t.Schema.Name == "Production")
  • 79. LINQ: Aggregate collections Sum() Returns the sum of the (numeric) values in the collection RootNode.Tables.Sum(t => t.Columns.Count) Average() Returns the average value of the (numeric) values in the collection RootNode.Tables.Average(t => t.Columns.Count)
  • 80. LINQ: Aggregate collections Min() Returns the minimum value of the (numeric) values in the collection RootNode.Tables.Min(t => t.Columns.Count) Max() Returns the maximum value of the (numeric) values in the collection RootNode.Tables.Max(t => t.Columns.Count)
  • 81. LINQ: Check collections All() Returns true if all elements in the collection meet the criteria RootNode.Databases.All(d => d.Name.StartsWith("A")) Any() Returns true if any element in the collection meets the criteria RootNode.Databases.Any(d => d.Name.Contains("DW"))
  • 82. LINQ: Check collections Contains() Returns true if collection contains element RootNode.Databases.Contains(AdventureWorks2014)
  • 83. LINQ: Get elements First() Returns the first element in the collection (that meets the criteria) RootNode.Tables.First() RootNode.Tables.First(t => t.Schema.Name == "Production") FirstOrDefault() Returns the first element in the collection or default value (that meets the criteria) RootNode.Tables.FirstOrDefault() RootNode.Tables.FirstOrDefault(t => t.Schema.Name == "Production")
  • 84. LINQ: Get elements Last() Returns the last element in the collection (that meets the criteria) RootNode.Tables.Last() RootNode.Tables.Last(t => t.Schema.Name == "Production") LastOrDefault() Returns the last element in the collection or default value (that meets the criteria) RootNode.Tables.LastOrDefault() RootNode.Tables.LastOrDefault(t => t.Schema.Name == "Production")
  • 85. LINQ: Get elements ElementAt() Returns the element in the collection at the specified index RootNode.Tables.ElementAt(42) ElementAtOrDefault() Returns the element in the collection or default value at the specified index RootNode.Tables.ElementAtOrDefault(42)
  • 86. LINQ: Project collections Select() Creates a new collection from one collection A list of table names: RootNode.Tables.Select(t => t.Name) A list of table and schema names: RootNode.Tables.Select(t => new {t.Name, t.Schema.Name})
  • 87. LINQ: Project collections SelectMany() Creates a new collection from many collections and merges the collections A list of all columns from all tables: RootNode.Tables.SelectMany(t => t.Columns)
  • 88. How is LINQ used in Biml projects?
  • 90. C# Classes and Methods BimlScript and LINQ not enough? Need to reuse C# code? Create your own classes and methods!
  • 91. C# Classes and Methods: From this… public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { if (node.GetTag(tag) != "") { return true; } else { return false; } } }
  • 92. C# Classes and Methods: …to this public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { if (node.GetTag(tag) != "") { return true; } return false; } }
  • 93. C# Classes and Methods: …to this public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 94. C# Classes and Methods: …to this public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != ""); } }
  • 95. Where do you put your C# code? Inline code nuggets Included Biml files with code nuggets Reference code files
  • 96. C# Classes and Methods: Inline <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #> ... <# } #> <# } #> </Biml> <#+ public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } } #>
  • 97. C# Classes and Methods: Included Files <#@ include file="HelperClass.biml" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #> ... <# } #> <# } #> </Biml> <#+ public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } } #>
  • 98. C# Classes and Methods: Code Files <#@ code file="HelperClass.cs" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #> ... <# } #> <# } #> </Biml> public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 100. Extension Methods "Make it look like the method belongs to an object instead of a helper class"
  • 101. Extension Methods: From this… <#@ code file="HelperClass.cs" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #> ... <# } #> <# } #> </Biml> public static class HelperClass { public static bool AnnotationTagExists(AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 102. Extension Methods: …to this <#@ code file="HelperClass.cs" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (HelperClass.AnnotationTagExists(table, "SourceSchema")) { #> ... <# } #> <# } #> </Biml> public static class HelperClass { public static bool AnnotationTagExists(this AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 103. Extension Methods: …to this <#@ code file="HelperClass.cs" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables) { #> <# if (table.AnnotationTagExists("SourceSchema")) { #> ... <# } #> <# } #> </Biml> public static class HelperClass { public static bool AnnotationTagExists(this AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 104. Extension Methods: …to this :) <#@ code file="HelperClass.cs" #> <Biml xmlns="http://schemas.varigence.com/biml.xsd"> <# foreach (var table in RootNode.Tables.Where(t => t.AnnotationTagExists("SourceSchema")) { #> ... <# } #> <# } #> </Biml> public static class HelperClass { public static bool AnnotationTagExists(this AstNode node, string tag) { return (node.GetTag(tag) != "") ? true : false; } }
  • 105. Get things done Start small Start simple Start with ugly code Keep going Expand Improve Deliver often
  • 108. THANK YOU TO OUR SPONSORS