LinqPad - Helmut-Ortmann/EnterpriseArchitect_hoTools GitHub Wiki
If you want to analyze your EA model with SQL, you should consider using LINQPad. Write the query once for all your database types. Use the combination of SQL like syntax, modern .net languages like C#, VB and the compiler to find your typos.
The main benefits are:
- Test your code and or query (SQL,XML,) interactive
- Combine SQL like query language with the power of C#, VB, or F#
- LINQ to have a common foundation for query of SQL, XML, Lists,
- Database independent
- IntelliSense, AutoComplete
- Let the compiler find your typos
- Debug and powerful outputs
- Run query per batch or command
- Tight integration in hoTools
- hoTools uses the fitting LINQPad connection
- hoTools: Class LINQPad to encapsulate running LINQPad from your AddIn
- AddInSimple: Example to run a LINQPad query from your AddIn
- AddInSimple: Example SQL Query to get the requirent types of the EAExample.eap
- AddInSimple: Example XML Query to get your EA Searches from XML
- AddInSimple: XML Query to output the availabel Database connections
The off-the-shelf interactive query and debugging tool:
- EA query
- Analyze without SQL limitations
- Verify complex rules
- Make metrics for your management
-
LINQPad abilities:
- Interactive, let you help by
- Compiler
- Intellisense
- Autocomplete
- Debugging
- LINQ to SQL (all the possible EA databases)
- LINQ to Object
- LINQ to XML
- C#, F#, VB, SQL
- Comprehensive Samples to see it working (learn LINQ, .net language like C#, VB, and more)
- Tip: Load more free samples
- etc.
- Interactive, let you help by
Write it once and use it for all your EA databases - regardless of location or type. Just connect your query with the new Database.
Let's see an example using SPARX EAExample.eap: "Get the count of your requirements ordered by requirement type"
You can export the LINQPad results to Excel,
// Requirement summary:
// - Type
// - Count
// - Percentage
// - Total count of requirements
var countReq = t_object.Where(e => e.Object_Type == "Requirement").Count();
var query =
(from c in t_object.AsEnumerable()
where c.Object_Type == "Requirement"
group c by c.Stereotype into g
orderby g.Key
select new
{
Type = (g.Key == null) ? "Simple" : $"<<{g.Key}>>",
Prozent = $"{ (float)g.Count() * 100 / countReq:00.00}%",
Count = g.Count(),
Total = countReq
});
query.Dump("EAExample JET, SqlServer, MySQL,..");
You may use the EA Context. hoTools contains the function LinqPad.GetArg() to collect the context. AddInSimple shows it as running example..
Let the Compiler find your typos.
Just for fun: Try it with SQL.
You want to explore the EA database. See what tables and columns exists. Peek into some details with just a few clicks, without any SQL or LINQ to SQL knowledge.
hoTools:LinqToSql provides some useful helper functions.
- Write queries database independent
- Combine queries like "query", "countReq",..
- IntelliSence, Autocomplete, Compiler finds your typos
- Arbitrary complex queries without the limitations of SQL and the different dialects
- Use code (C#,VB, F#)
- Same query independent of Database (all EA Databases supported)
- LINQPad as an interactive query and debugging tool
- Interactive develop, debug and see your valuable EA data on the spot
- Use it in your Add-In (hoTools use LINQ to SQL, AddInSimple has to examples)
- Create a new connection to your EA Database
- Assign this connection to the query at hand
- Enter the query and execute
With the LINQPad templates you can quickly explore your repository.
In principle LINQ to SQL should be database independent. Different database providers may differ in e.g. name of the table (upper/lower cases). Therefore it's a good idea to try to use only one database provider to avoid such trouble.
My tests with EA, the databases Access, SQL Server and MySQL together with linq2db database providers work fine. Once, I used the Microsoft SQL driver and found that the table names startet with 'T_' instead of 't_' in case of linq2db drivers.
On the left side of LINQPad you have to add possible connections to your EA Databases you want to query on:
- Add Connection
- Only once: Install wanted driver
- View more drivers
- Choose your driver (I have chosen LINQ to DB Driver (open source)
- DownLoad and install
- Select driver
- Enter connection string
- Test
Note: The dialogs to parametrize a connection to a LINQ SQL Provider may differ. I've tested it with the linq2db driver. The linq2db driver e.g does't supports ODBC DSN names like "DSN=MyLovelyEA;".
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Program Files (x86)\Sparx Systems\EA\EAExample.eap;
If you use only SQL Server you can also stick to the standard SQL Server driver from Microsoft.
Server=localhost\SQLEXPRESS;Database=EAExample;Trusted_Connection=True;
Server=localhost;Database=eaexamplemysql;Uid=;Pwd=;
void Main(string[] args)
{
// process id
int pid = 0;
//
// Use CMD symbol to check whether you're running in the GUI or from the command line, you can do this as follow
// see: https://www.linqpad.net/lprun.aspx
#if CMD
// run from command line via lprun
if (args != null && args.Length > 0)
{
pid = Int32.Parse(args[0]);
"_".Dump($"Run by Batch for process '{pid}'");
}
#else
// run in LINQPad GUI
"_".Dump("Run by Dialog");
// Get PID of EA
Process processEa = Process.GetProcessesByName("EA").FirstOrDefault();
if (processEa == null)
{
MessageBox.Show("","Can't determine running ea.exe instance!");
return;
}
pid = processEa.Id.Dump("ProcessID");
#endif
// run for found EA instance
if (pid > 0)
{
Program p = new Program(pid);
EA.Repository rep = p.Repository;
rep.ConnectionString.Dump();
}
}
//---------------------------------------------------------
// Get the Repository from the program ID
//---------------------------------------------------------
// This method is used to call this script from EA and access the Repository the call comes from
//
class Program
{
private EA.Repository _repository = null;
private int m_ProcessID = 0;
// get the EA repository from the progid
public Program(int pid)
{
m_ProcessID = pid;
_repository = SparxSystems.Services.GetRepository(m_ProcessID);
Trace("Running C# Console Application AppPattern .NET 4.0");
}
public EA.Repository Repository
{
get { return _repository;}
}
public void Trace(string msg)
{
if (_repository != null)
{
// Displays the message in the 'Script' tab of Enterprise Architect System Output Window
_repository.WriteOutput("Script", msg, 0);
}
Console.WriteLine(msg);
}
}
- Access to database via Linq2db
- Access via COM automatisation and connection string.
void Main()
{
//----------------------------------------------------------------------------------------------
// EaAutomationTemplate
//----------------------------------------------------------------------------------------------
//
// Template to access EA with two strategies:
// - LINQ to DB
// - Native access to an EA Repository and access via COM and EA API (Interop.EA.dll)
// - opening *.eap file
string provider = "Access";
// see: http://sparxsystems.com/enterprise_architect_user_guide/14.0/automation/repository3.html
// Repository.OpenFile();
// - path to *.eap(x) file, might be a shortcut to a DBMS/SQL Database
// - connections string
string repositoryPath = @"c:\Users\helmu\AppData\Roaming\Sparx Systems\EA\EAExample.eap";// Example database
// Access to Repository
EA.Repository rep = new EA.Repository();
rep.OpenFile(repositoryPath);
rep.ConnectionString.Dump();
// Use LINQ to SQL
// Use connection to SPARX Example Database
string newConnectionString = ConstructConnectionString(Connection.ConnectionString, repositoryPath);
using (TypedDataContext db = new TypedDataContext(provider, newConnectionString))
{
var rootPackages = from pkg in db.t_package
where pkg.Parent_ID == 0
orderby pkg.Name
select new { Name=pkg.Name, Package =pkg.Ea_guid};
rootPackages.Dump();
}
}
// Define other methods and classes here
// ------------------------------------------------------------------------------------------------------------------
// ConstructConnectionString
// ------------------------------------------------------------------------------------------------------------------
// Construct the connection string from datasource. This you can use to make a connection to the wanted connection by:
// - TypedDataContext db = new TypedDataContext("SQLite", newConnectionString);
// - TypedDataContext db = new TypedDataContext("Access", newConnectionString);
//
// Note: You uses the definitions of the used LINQPad connection
//
public string ConstructConnectionString(string oldConnection, string dataSource)
{
Regex rx = new Regex(@"Data Source=[^;]*;");
return rx.Replace(oldConnection, $"Data Source={dataSource};");
}
Sometimes you get weird error messages. Something about SQL and LINQ to SQL can't...
Don't worry. LINQ to SQL tries to do a lot with SQL. Sometimes it easy doesn't add up. If you encounter such behavior: Force LINQ to work in memory.
// Process in memory to avoid SQL Access (e.g. string.Join(", ", isn't supported by Access SQL)
var tempRead = read.ToList().AsEnumerable(); //.Dump("Read in memory");
var tempWrite = write.ToList().AsEnumerable(); //.Dump("Write in memory");;
var combined = tempRead.Concat(tempWrite).AsEnumerable(); //.Dump("Combined in memory");
It's simple. Just write your query to list by "write.ToList().AsEnumerable();". After that, you can work with the query, and you are sure that LINQ to SQL doesn't translate it into SQL.
hoTools shows the first table named 't1' as grid in the EA Model Search window. hoTools doesn't support:
- LINQPad Hierachical views
- More than one table (hoTools shows only the first table/view)
LINQ to SQL is the solution for complex queries: