I am looking for a way to create a script component within SSIS which will accept multiple inputs.
I need this so I can do a form of custom joining.
It seems really silly that a script can have multiple outputs but only one input, I'm sure I must be doing something wrong.
Any help?
try putting a Union All component before your script component, and rather than having the columns match up, add columns to the output so that each element coming in winds up in a unique column.
Keep in mind that at first the SSIS script component will process items row by row, so a custom joining mechanism will need to be done using some collections and capturing the event that fires after all the rows have been processed.
Please keep in mind that I'm assuming you're using a script component in the Data Flow and not the Control Flow, and that I'm assuming you're using SSIS 2005.
I'm currently experimenting with using SSIS variables to pass synchronization objects from one script component to another. It's rather clumsy, but you can effectively use multiple script components to accept various inputs, and then use the System.Threading classes to sync passing values from one script component to another.
The hurdle is that each script is in its own namespace and can't share classes with other scripts (unless you want to compile & deploy your own assembly with SSIS). What I'm currently doing is passing (over the shared variable) a reference to an object[], containing a reference to a ManualResetEvent, the SSIS PipelineBuffer, and an array of pipeline column indices.
This is enough to allow the receiving script to reconstruct the other script's input pipeline, pump it dry, then signal back that it's finished.
It's functional, though I'm currently looking for work-arounds to the fact that (it would seem) SSIS invokes "ProcessInput" twice during a script component's life time. If any of the geniuses here on SO have a solution to that, then I think we've pretty much got a [clumsey] solution to allowing multiple inputs to a single script component.
Any takers?
---- EDIT----
I've got this up and running - this trick is to use syncronization to prevent the multi-threaded invocation of ProcessInput from attempting to share th input buffer mulitple times. Below is a crude code sample of how I got this working:
Script Component 1: Shares its input...
using System;
using System.Collections;
using System.Threading;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.SqlServer.Dts.Pipeline;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
System.Collections.Generic.List<object> shared = null;
System.Threading.ManualResetEvent sync;
public override void ProcessInput(int InputID, PipelineBuffer Buffer)
{
lock (this)
{
if (InputID == 82)
{
if (shared == null)
{
shared = new System.Collections.Generic.List<object>();
sync = new System.Threading.ManualResetEvent(false);
shared.Add(sync);
shared.Add(Buffer);
shared.Add(GetColumnIndexes(InputID));
IDTSVariables100 vars = null;
this.VariableDispenser.LockOneForWrite("Test", ref vars);
vars[0].Value = shared;
vars.Unlock();
sync.WaitOne();
System.Windows.Forms.MessageBox.Show("Done");
}
}
}
}
}
... then Script Component 2 (which consumes Script Component 1's input)...
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
System.Threading.ManualResetEvent sync = null;
InputXBuffer sharedBuffer = null;
public override void Input0_ProcessInput(Input0Buffer Buffer)
{
lock (this) // Only 1 thread at a time
{
if (sharedBuffer == null)
{
object Test = null;
while (Test == null)
{
System.Threading.Thread.Sleep(100);
IDTSVariables100 vars = null;
this.VariableDispenser.LockOneForRead("Test", ref vars);
Test = vars[0].Value;
vars.Unlock();
}
var sharedList = Test as System.Collections.Generic.List<object>;
if (sharedList != null)
{
sync = sharedList[0] as System.Threading.ManualResetEvent;
var buffer = sharedList[1] as PipelineBuffer;
var bufferColumnIndexes = sharedList[2] as int[];
sharedBuffer = new InputXBuffer(buffer, bufferColumnIndexes);
}
}
}
while (sharedBuffer.NextRow())
{
// ... do stuff with Script Component 1's shared input here...
}
sync.Set(); // Signal script 1 that we're done
}
}
The scripts both share a read/write variable called "Test" - you can change the variable name to suite your needs. Hopefully the above serves as a working model for you to take this to the next level.
PS:- If you have the time & energy, writing a proper custom SSIS component really is the way to go for multi input scenarios.
Related
Following the answer here, I have created a file called MyGlobals.as and placed some global variables and functions so that I can access it from anywhere within my project just like AS3 buil-in functions such as trace() method.
This is MyGlobals.as which is located in the src folder (top level folder)
package {
public var MessageQueue:Array = new Array();
public var main:Main;
public var BOOKING_STATUS_DATA:Object;
public function postMessage(msg:Object):void {
MessageQueue.push(msg);
}
public function processMessage():void {
var msg:Object = MessageQueue.pop();
if (msg) {
switch (msg.type) {
}
}
}
Looks like my IDE (FD4) is also recognizing all these functions and variables and also highlighting the varibles and functions just like any other built-in global functions. However, I am getting compilation errors "Accessing possibly undefined variable xxx". The code is as simple as trace(MessageQueue) inside my Main (or another classe).
I am wondering if there was any change Adboe has done recently that it can't be done now or am I missing something? I am not sure if I need to give any special instructions to FD to include this MyGlobals.as?
I am using FD4, Flex SKD 3.1, FP12.0
I am aware of the best practices which suggests to avoid using this type of method for creating global variables but I really need it for my project for my comfort which I feel best way (right now) when compared to take any other path which involves daunting task of code refactoring. I just want do something which can be done in AS3 which I guess is not a hack.
I've done some playing around; it looks like you can only define one (1) property or method at package level per .as file. It must be the same name (case-sensitive) as the .as file it is contained in.
So no, nothing has changed since the older Flash Versions.
In your case that would mean you need five separate ActionScript files along the lines of:
MessageQueue.as:
package
{
public var MessageQueue:Array;
}
main.as:
package
{
public var main:Main;
}
...etc. As you can see this is very cumbersome, another downside to the many others when using this approach. I suggest using the singleton pattern in this scenario instead.
package{
public class Singleton{
private static var _instance:Singleton=null;
private var _score:Number=0;
public function Singleton(e:SingletonEnforcer){
trace(‘new instance of singleton created’);
}
public static function getInstance():Singleton{
if(_instance==null){
_instance=new Singleton(new SingletonEnforcer());
}
return _instance;
}
public function get score():Number{
return _score;
}
public function set score(newScore:Number):void{
_score=newScore;
}
}
}
then iin your any as3 class if you import the singleton class
import Singleton
thn where u need to update the global var_score
use for example
var s:Singleton=Singleton.getInstance();
s.score=50;
trace(s.score);
same thing to display the 50 from another class
var wawa:Singleton=Singleton.getInstance();
trace(wawa.score)
My current project is in as3, but this is something I am curious about for other languages as well.
I'm attempting to use a factory object to create the appropriate object dynamically. My LevelFactory has a static method that returns a new instance of the level number provided to the method. In the code calling that method, I am able to dynamically create the buttons to call the levels like so:
for (var i:int = 1; i < 4; i++) {
var tempbutton:Sprite = createButton("Level " + i, 25, 25 +(60 * i), start(i));
_buttons.push(button);
}
This code just creates a simple button with the given arguments (ButtonText, x, y, function). It's working fine. The buttons are created, and clicking on one of them calls this method with the appropriate argument
private function start(level:int):Function {
return function(e:MouseEvent):void {
disableButtons();
newLevel = LevelFactory.createLevel(level);
addChild(newLevel);
}
}
This is all working fine; I'm just providing it for background context. The question I have is this: Is it possible to dynamically choose the type of object that my static function returns? Currently, I have am doing it as follows
public static function createLevel(level:int):Level {
var result:Level;
switch(level) {
case 1: result = new Level1(); break;
case 2: result = new Level2(); break;
//etc
}
return result;
}
I should note that all of these Level1, Level2, etc. classes extend my base level class. (Yay polymorphism!) What I would like to do is be able to do something along the lines of
public static function createLevel(level:int):Level {
var result:Level;
var levelType:String = "Level" + level;
return new levelType();
}
Obviously it's not going to work with a string like that, but is there any way to accomplish this in as3? What about other languages, such as Java or Python? Can you dynamically choose what type of child class to instantiate?
Update:
import Levels.*;
import flash.events.*;
import flash.utils.*;
public class LevelFactory
{
public static function createLevel(level:int):Level {
var ref:Class = getDefinitionByName('Levels.' + 'Level' + level) as Class;
var result:Level = new ref();
return result;
}
}
Update/Edit: getDefinitionByName seems to be what I'm looking for, but it has a problem. It seems that the compiler will strip unused imports, which means that unless I declare each subclass in the code ahead of time, this method will get a reference error. How can I get around the need to declare each class separately (which defeats the purpose of dynamic instantiation)?
Yes, you sure can, and it's very similar to the string thing that you've provided. The only thing that you are missing is the getDefinitionByName method: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/package.html#getDefinitionByName()
You can generate whatever class name you want, and what this method does is that it searches for that class in it's namespace, and if it finds it - it returns it as a class:
var ClassReference:Class = getDefinitionByName("flash.display.Sprite") as Class;
var instance:Object = new ClassReference();
This piece of code will instantiate a Sprite. This way you can instantiate your classes without all those switches and cases, especially when you have to make a hundred levels :)
Hope that helps! Cheers!
Edit:
In your case, the code should be:
var ref:Class = getDefinitionByName('com.path.Level' + index) as Class;
var level:Level = new ref(); // it will actually be Level1 Class
Since Andrey didn't quite finish helping me out, I am writing up a more complete answer to the question after much research.
getDefinitionByName definitely has the use I am looking for. However, unlike its use in Java, you HAVE to have a hard reference to the class you want instantiated somewhere in your code. Merely imported the class is not enough; the reason for this is that the compiler will strip the reference from any unused import to save space. So if you import the package of classes you want to choose dynamically but don't have a hard reference to them, the compiler will de-reference them. This will lead to a run-time error when the program cannot find the appropriate reference to your class.
Note that you don't actually have to do anything with the reference. You just have to declare a reference so that it can be found at run-time. So the following code will work to eliminate the switch-case statement and allow me to dynamically declare which class I am using at run-time.
{
import Levels.*;
import flash.events.*;
import flash.utils.*;
/**
*
* Returns the requested level using the createLevel class
* ...
* #author Joshua Zollinger
*/
public class LevelFactory
{
Level1, Level2, Level3, Level4, Level5, Level6, Level7;
public static function createLevel(level:int):Level {
var ref:Class = getDefinitionByName('Levels.Level' + level) as Class;
var result:Level = new ref(); // it will actually be the correct class
return result;
}}}
The obvious downside to this is that you still have to have a hard-coded reference to every class that can be instantiated like this. In this case, if I try to create a Level8 instance, it will through a run-time error because Level8 is not referenced. So every time I create a new level, I still have to go add a reference to it; I can't just use the reference dynamically.
There are supposedly ways around this that I have not tested yet, such as putting the code for the classes in a separate SWF and importing the SWF at run-time or using outside libraries that will have different functionality. If anyone has a solid way to get a truly dynamic reference that doesn't require a hard coded reference anywhere, I would love to hear about it.
Of course, it's still a lot cleaner this way; I don't have a extensive switch case statement to pack all the levels. And it's easier and faster to add a reference to the list than creating a new case in a switch. Plus it is closer to dynamic programming, which is usually a good thing.
A number of our MVVMcross views depend remote services to fully display themselves. We typically kick this off a Task in ViewModel's Init() using to get it async. ViewModel properties are set in the Task upon completion, UI updated via PropertyChanged notifications.
Sometimes the remote data (and task) completes before the View has bound it's listeners and thus no property changed event is received.
This issue is touched on at async Init and Property Changed in MvvmCross but the solution feels like duplication of presentation logic.
We've had success buffering PropertyChanged notifications until the end of ViewDidLoad, but we'd like to turn below into a more generic solution by hooking into the MVX framework.
Is there a way to hook mvvmcross's view creation to fire our code off after viewDidLoad completes?
Base View Model
public abstract class BaseViewModel : MvxViewModel{
protected bool _deferPropertyChangedEvents = true;
private readonly List<PropertyChangedEventArgs> _deferedPropertyChangedEvents = new List<PropertyChangedEventArgs>();
public override void RaisePropertyChanged(PropertyChangedEventArgs changedArgs)
{
lock(_deferedPropertyChangedEvents){
if (!_deferPropertyChangedEvents)
{
base.RaisePropertyChanged(changedArgs);
}
else
{
// buffer it up
_deferedPropertyChangedEvents.Add(changedArgs);
}
}
}
public void EndDeferringPropertyChangedEvents()
{
lock(_deferedPropertyChangedEvents){
_deferPropertyChangedEvents = false;
// playback all buffered notifications
foreach (var e in _deferedPropertyChangedEvents)
{
RaisePropertyChanged(e);
}
_deferedPropertyChangedEvents.Clear();
}
}
}
Sample view
public class SomeView : MvxViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
var bindings = this.CreateBindingSet<StopView, SomeViewModel>();
.....
bindings.Apply();
// plays back any PropertyChanged() notifications that were buffered
// up while the view was initializing
// ---> want to find a way to have MVX call this
ViewModel.EndDeferringPropertyChangedEvents();
}
}
As a simple answer, I believe your own line can easily be called using a BaseViewModel cast:
// ---> want to find a way to have MVX call this
((BaseViewModel)ViewModel).EndDeferringPropertyChangedEvents();
However, on a more technical note, I think it might be useful to further examine and understand why this Deferring code is necessary - to further take a look at what the underlying threading problems are.
There are a number of factors that are puzzling me at present::
During the line bindings.Apply(); all current bound property values should be transferred from the ViewModel to the View - so calling EndDeferringPropertyChangedEvents(); in the next line should (in theory) only rarely get different values.
Further, the default MvvmCross RaisePropertyChanged method changed notifications across to the UI thread. Because ViewDidLoad is also invoked on the UI thread, this means that any RaisePropertyChanged calls made on background threads during ViewDidLoad should all be automatically deferred until after ViewDidLoad has finished and the UI thread becomes available.
Looking at the MvxNotifyPropertyChanged code, the only potential gap I can see where mutli-threading might find a way through this automatic RaisePropertyChanged deferral is in this optimisation check:
// check for subscription before potentially causing a cross-threaded call
if (PropertyChanged == null)
return;
(from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs#L76)
If your ViewModel Init method is also using async for it's Task management, then this async code should also be using the UI thread - so the "callback" of this async operation should also be marshalled back to the UI thread (and so shouldn't be executed during ViewDidLoad itself).
As I said, these factors are puzzling me - I don't have a definitive answer/explanation - sorry! But I'd love to see an example problem and to try to help solve it at a generic level.
I have been using Mvvmcross to develop Android application. I am dealing with the issue of ViewModel lifecycle during a rotation. It seems that generally ViewModel is preserved during a rotation. However this is not the case when I present ViewModels in MvxTabActivity. When the rotation happens it always calls a ViewModel constructor.
I have used similar code structure as in N+1 tutorial https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-25-Tabbed.
Is there a way to modify this tutorial to keep ViewModels in memory during rotation when using MvxTabActivity?
The default ViewModel caching which attempts to workaround the Android rotation behaviour is based around IMvxSingleViewModelCache - so it's not too surprising it can't cope with multiple Activities and multiple ViewModels.
For where this interface is declared and used, see https://github.com/slodge/MvvmCross/search?q=IMvxSingleViewModelCache&ref=cmdform
If this behaviour is troubling you, then you should be able to work around it by one of :
1. Use fragment based tabs rather than Activity based ones
Android handles Fragment lifecycle differently to Activity ones.
2. Or continue using activity based tabs, but implement your own IMvxSingleViewModelCache
It should be simple, for example, to identify your child view models with by their 'Child' naming convention.
With this done you can then implement something like:
public class MyCustomViewModelCache
: IMvxSingleViewModelCache
{
private const string BundleCacheKey = "__mvxVMCacheKey";
private int _counter;
private IMvxViewModel _currentViewModel;
public void Cache(IMvxViewModel toCache, Bundle bundle)
{
if (toCache != null
&& toCache.GetType().Name.StartsWith("Child"))
{
// don't worry about caching child view models
return;
}
_currentViewModel = toCache;
_counter++;
if (_currentViewModel == null)
{
return;
}
bundle.PutInt(BundleCacheKey, _counter);
}
public IMvxViewModel GetAndClear(Bundle bundle)
{
var storedViewModel = _currentViewModel;
_currentViewModel = null;
if (bundle == null)
return null;
var key = bundle.GetInt(BundleCacheKey);
var toReturn = (key == _counter) ? storedViewModel : null;
return toReturn;
}
}
This class based on MvxSingleViewModelCache.cs with just one small addition.
You can register an instance of this class as the IMvxSingleViewModelCache singleton during the InitializeLastChance of your Setup.
Mvx.RegisterSingleton<IMvxSingleViewModelCache>(new MyCustomViewModelCache());
With this done, the home/tab activity should (I think) continue to work - and it'll pass the viewmodels down to the tab children after rotation.
(Other possibilities for IMvxSingleViewModelCache are possible - e.g. it could cache multiple view models - but please don't let it cache too many view models for too long or you may run into 'out of memory' conditions)
3. Or switch the Android rotation handling off
If you add the android:configChanges="orientation" flag (or it's monodroid equivalent Attribute) then you can just handle the rotation yourself.
I am writing an iOS game in Flash and I need a way to clone polymorphic objects.
I have BaseClass, SubClass1, SubClass2 (and so on...) and I need a clone() method in BaseClass, that will create a copy of the current object, without a conditional such as
var obj:BaseClass;
if(this is SubClass1) {
obj = new SubClass1();
}else if(this is SubClass2) {
obj = new SubClass2();
}else...
I need a way to create an object and create the exact bytes (yes, a shallow copy is enough for my purpose) of the object. I've looked at:
AS3 - Clone an object
As3 Copy object
http://actionscripthowto.com/how-to-clone-objects-in-as3/
But none seem to work. Probably not available in AIR 3.3 for iOS SDK. (they compile, but the code doesn't work in my case)
Is there any other way, or did anybody achieve to clone an object in AIR for iOS?
Thanks,
Can.
Bit-by-bit cloning cannot be done with ActionScript, unless your class only contains primitive values (i.e. a simple data structure). That's what the ByteArray approach you've linked to in this question's answer is used for - but when you're dealing with complex types, especially display objects, you'll soon come to the limits (as, I gather, you have already realized).
So this more or less leaves you with two options:
Create a new object and copy all of its fields and properties.
This is the way to go if you're going to need behavior and field values, and you didn't use any drawing methods (i.e., you can not copy vector graphics this way). Creating a new class instance without knowing its exact type can be done in a generalized way using reflections, getQualifiedClassName() and getDefinitionByName() will help you there, and if you need more than just the name, describeType(). This does have limits, too, though:private fields will not be available (they don't appear in the information provided by describeType()), and in order to not run into performance problems, you will have to use some sort of cacheing. Luckily, as3commons-reflect has already solved this, so implementing the rest of what you need for a fully functional shallow copy mechanism is not too complex.
Create a new instance like this:
var newObject:* = new Type.forInstance( myObject ).clazz();
Then iterate over all accessors, variables and dynamic properties and assign the old instance's values.
I have implemented a method like this myself, for an open source framework I am working on. You can download or fork it at github. There isn't any documentation yet, but its use is as simple as writing:
var myCopy:* = shallowCopy( myObject );
I also have a copy() method there, which creates a true deep copy. This, however, has not been tested with anything but data structures (albeit large ones), so use at your own risk ;)
Create a bitmap copy.
If you do have vector graphics in place, this is often easier than recreating an image: Simply draw the content of the object's graphics to a new Bitmap.
function bitmapCopy( source:Sprite ):Bitmap {
source.cacheAsBitmap = true;
var bitmapData:BitmapData = new BitmapData( source.width, source.height, true, 0xFFFFFF );
bitmapData.draw( source, new Matrix(), null, null, null, true );
return new Bitmap( bitmapData, PixelSnapping.AUTO, true );
}
You need to create an abstract clone method in the base class and implement it for each subclass. In the specific implementations, you would copy all of the properties of the object to the new one.
public class BaseClass {
public function clone():BaseClass
{
// throw an error so you quickly see the places where you forgot to override it
throw new Error("clone() should be overridden in subclasses!");
return null;
}
}
public class Subclass1 extends BaseClass {
public override function clone():BaseClass
{
var copy:Subclass1 = new Subclass1();
copy.prop1 = prop1;
copy.prop2 = prop2;
// .. etc
return copy;
}
}
If you wanted to create a generic default implementation of clone, you could use describeType to access the properties and copy them over:
public function clone():BaseClass
{
var defn:XML = describeType(this);
var clsName:String = defn.#name;
var cls:Class = getDefinitionByName(clsName) as Class;
var inst:* = new cls();
for each(var prop:String in (defn.variable + defn.accessor.(#access == 'readwrite')).#name )
{
inst[prop] = this[prop];
}
return inst;
}
The main issue with this is that the describeType XML can get quite large - especially if you are dealing with objects that extend DisplayObject. That could use a lot of memory and be slow on iOS.