What I need
Step 1
I need to do an export of all information, whatever the node type, under a main root node (= package).
Step 2
Using that export information I need to do a mapping to a JSON contract provided by a third party.
Step 3
The third party can then use my JSON to import the information from EA into their system.
What I have
Step 1 is completed, I have a file based data dump on my target location like this:
Basically that's a static html website which corresponds to the EA structure by displaying the information in a tree-view, similar to how you see it in EA.
What I can do
Is go through the EARoot folder and read all information provided in the html files that are in there.
In my case EARoot contains three subfolders:
Where the EA1 subfolders contains
The html files contain the information I need, it's doable to interpret the data in a meaningful fashion.
The catch
Is that there's no immediate link to the files and the actual node structure in EA. I can make an assumption based on the available data, that will work -most- of the time, but it needs to be reliable and work -all- the time.
I can find a correct UUID in each html file, so that would be a way to link to the structure, but to find this structure, I need to be able to get the UUIDS of all children of a node and go through the tree recursively.
I tried the following:
public Package GetRootPackage()
{
using (var repo = EnterpriseArchitect.Repository.Open(_connectionString))
{
return repo.GetPackage(this.RootPackageName);
}
}
EnterpriseArchitect.Repository is a wrapper on top of EA.Repository to have it be IDisposable for better connection management.
Using the GetRootPackage method defined above, I can connect and load the node I want:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
I'd think that I'd then be able to fetch it's children like so:
var children = root.Packages;
But then I get this nasty error:
System.Runtime.InteropServices.COMException HResult=0x80010105
Message=The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)) Source=my.console
StackTrace: at EA.IDualPackage.get_Elements() at my.console.Program.Main(String[] args) in C:\Repos\my.console\Program.cs:line 29
I checked eventviewer for more information and found (only) this:
Faulting application name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Faulting module name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Exception code: 0xc0000005
Fault offset: 0x0049ffc4
Faulting process id: 0x2eac
Faulting application start time: 0x01d56eb6d931a965
Faulting application path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Faulting module path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Report Id: 223f8c89-c84a-45c6-9100-82af8e94643a
Faulting package full name:
Faulting package-relative application ID:
The question
What I find regarding this HResult=0x80010105
seems to be Excel related, so I'm not sure if that's meaningful.
I'm running from a console, because I understood that interop.EA
should be considered to be not-threadsafe.
What can I do to avoid this issue and get the child packages?
It's the IDisposable
wrapper on top of EA.Repository
that's causing the issue. If I call the repo directly (using try catch finally
instead of IDisposable
) I am able to get the child nodes.
So much for defensive programming ...
Instead of the wrapper I had:
public class Repository : IDisposable
{
private EA.Repository _repo;
protected Repository(string connectionString)
{
_repo = new EA.Repository();
_repo.OpenFile(connectionString);
}
...
public void Dispose()
{
_repo.CloseFile();
_repo = null;
}
}
I'm now using the EA repo directly to get (root) package information:
public Package GetRootPackage()
{
var repo = new EA.Repository();
try
{
repo.OpenFile(_connectionString);
var pkg = (EA.Package)repo.Models.GetByName(this.RootPackageName);
if (pkg is null)
throw new ApplicationException($"Package \"{this.RootPackageName}\" not found.");
return pkg;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
finally
{
Console.WriteLine("Closing repository...");
repo.CloseFile();
}
}
Through this I can do:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
foreach (var item in root.Packages)
{
var child = (IDualPackage)item;
var guid = child.PackageGUID;
}
And the guid
var contains the correct PackageGUID
.
User contributions licensed under CC BY-SA 3.0