Author Topic: Speed of moving elements between packages  (Read 2888 times)

MaXyM

  • EA User
  • **
  • Posts: 120
  • Karma: +8/-0
    • View Profile
Speed of moving elements between packages
« on: December 11, 2018, 09:42:56 pm »
As I mentioned somewhere else on this forum, I have to move objects between packages to improve user experience while working with database models. EA's DB RE imports all objects of the same type to single package regardless schema. And this location is mandatory for further work with RE. However for daily usage, we have to have split those objects into schema-based packages.
In result, every time I need to update EA model based on existing database, I have to move objects back and forth. With number of objects (thousands) it takes a lot of time (recently it took almost and hour, while running outside of working hours). Maybe worth to mention we are using central repository.

I'm moving the objects using scripting, in particular creating needed packages and changing packageID of each element.

Is there any way to speed this operation up, considering production model so any risky moves have to be limited. A few come to my mind:
- updating model using SQL queries against repo
- performing complete RE outside production model, then import via XMI

Both ways do look to me kinda dirty.
Maybe it's possible to speed up existing script, ie by some bulk update/refresh instead of doing it for single object separately. But I'm not sure what is allowed to do in this matter.

Here is a code I'm using for moving objects from original EA structure into Schemas/<schema_name>/<object_type>/<object> sctructure

Code: [Select]
!INC Local Scripts.EAConstants-JScript
!INC MichalK Scripts.Shared-Lib-JScript

/*
 * Script Name: DbObjects_ReorganizeIntoSchemasTypes
 * Author: Michal Kozusznik
 * Purpose: Move db objects located in object type packages (functions,tables and so on) into Schemas/schemaname/objecttype
 * Date: 2017-11-28
 */

function main()
{
Repository.EnsureOutputVisible( "Script" );
Session.Output( "Move tables to schemas-packages" );
Session.Output( "=======================================" );
var err;

MeasureTime();

try
{

var pck as EA.Package;
var RootSchemaPackageName = 'Schemas';

oType = Repository.GetTreeSelectedItemType();

if (oType != 5 /* package */) throw new Error("No package selected. Exiting.");

pck = Repository.GetTreeSelectedObject();

if (pck.StereotypeEx != 'Database') throw new Error("It is no root database package. Exiting.");

schemapackage = CreatePackageIfMissing(pck, RootSchemaPackageName);

for ( var i = 0 ; i < pck.Packages.Count ; i++)
{
if (pck.Packages.GetAt(i).Name == RootSchemaPackageName) continue;
Session.Output( "Processing: " + pck.Packages.GetAt(i).Name);
ProcessObjects(pck.Packages.GetAt(i), schemapackage);
}


Session.Output( "Finished" );
}
catch (err)
{
Session.Prompt(err.message, 0);
return;
}


Session.Output('Finished in: ' + MeasureTime() + 's');
}

/**********
 * Iterate through all elements found in <srcPck> package and move them into <schemaPck>
 * Inside of <schemaPck> subpackages representing db schemas will be created.
 * And inside of the latter, subpackages for object types (Functions, Tables etc)
 *
 * <schemaPck>
 *    schema1
 *       Functinos
 *       Sequences
 *       Tables
 *       Views
 *    schema2
 *       Functinos
 *       Sequences
 *       Tables
 *       Vies
 *    etc
 *
 ***********/
function ProcessObjects(srcPck, schemaPck)
{
var sourcePackage as EA.Package;
sourcePackage = srcPck;

var schema as EA.Package;


var currPackage as EA.Package;
var obj as EA.Element;

for ( var i = 0 ; i < sourcePackage.Elements.Count ; i++)
{

obj = sourcePackage.Elements.GetAt(i);
Session.Output( obj.Name);
schema = CreatePackageIfMissing(schemaPck, GetSchemaFromTaggedValue(obj));
currPackage = CreatePackageIfMissing(schema, sourcePackage.Name);

obj.PackageID = currPackage.PackageID;
obj.Update();
}

sourcePackage.Update();
schemaPck.Update();

}



/*
 * Find a <schemaname> package collection of <pck>, or create one if not existist.
*/
function CreatePackageIfMissing(pck, schemaname)
{
var currentObj as EA.Package;
var currentPackage as EA.Package;
currentPackage = pck;
currentObj = null;

try
{
currentObj = currentPackage.Packages.GetByName(schemaname);
}
catch (err)
{
// do nothing
}

if (currentObj == null)
{
currentObj = currentPackage.Packages.AddNew(schemaname, "Class");
currentObj.Update();
currentPackage.Packages.Refresh();
}


return currentObj;
}

/******
 * Get Schema name from 'Owner' TaggedValue of given <obj>
 ******/
function GetSchemaFromTaggedValue(obj)
{
var element as EA.Element;
var retval;
element = obj;

if (element.TaggedValues.GetByName('Owner') != null) retval = element.TaggedValues.GetByName('Owner').Value;
    else if (element.TaggedValues.GetByName('OWNER') != null) retval = element.TaggedValues.GetByName('OWNER').Value;

if (retval == null)
{
throw new Error('Element ' + element.Name + ' has no tagged value Owner');
}
return retval;
}

main();

Don't bother of included script. It provides MeasureTime() to measure script execution time. Nothing critical.

With regards
« Last Edit: December 11, 2018, 09:51:38 pm by MaXyM »

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 12914
  • Karma: +537/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Speed of moving elements between packages
« Reply #1 on: December 11, 2018, 09:59:53 pm »
There are a number of things you could do:

1. Instead of using Package.Elements, for each nested package, get the all the elements using an SQL query. You'll have to first get the nested package ID (so actually what EA does to expand the #Branch# macro) string to get all elements regardless of their owner package. See https://github.com/GeertBellekens/Enterprise-Architect-VBScript-Library/search?q=getPackageTreeIDString&unscoped_q=getPackageTreeIDString

This should already speed up the script

2. Never iterate an EA.Collection more then once. Store the objects in an ArrayList, or a Dictionary and iterate over that. EA.Collections are weird things that sometimes go back to the database when iterating. They are not your average collection class.

3. Update all of the the packageID's using Repository.Update(SQLQuery).
This is the nuclear option, but since it only involves a single field that needs to be updated I guess it would still be OK. Your script will probably finish in a few seconds if you use this option.

Geert

Ron Beernink

  • EA User
  • **
  • Posts: 24
  • Karma: +1/-0
    • View Profile
Re: Speed of moving elements between packages
« Reply #2 on: November 04, 2020, 07:48:58 am »
I found an issue workaround that avoids scripting.   Simply right click on the destination package and select to open this in a List View.   Then it is just a case of dragging elements from your package in the browser to the list view.