简体   繁体   中英

Object to List C# and SSIS

Background:

Bit of a strange one. Using SSIS to deal with data coming from an API, my first script gets the data and puts it against a strongly typed model called "TestModel"

The SSIS package then saves the resulting information to a variable which is then passed into the next part of the SSIS package. Being SSIS name spaces are not carried around so each script task is in isolation.

Script Task One Namespace: ST_a048e0de86e1432d8da6f60b5d7055db

Script Task Two Namespace: SC_0573a66ec6c0486a98ee00cea4365654

The Issue:

The second SSIS script task picks up the variable and reads it fine, I can in debug see all my rows and all the relevant data. Now things start getting weird, the type of the List when it reaches my second script

object {System.Collections.Generic.List<ST_a048e0de86e1432d8da6f60b5d7055db.TestModel>}

Each of the objects in this Generic.List has the Type of:

ST_a048e0de86e1432d8da6f60b5d7055db.TestModel

What can I do with this list? Pretty much nothing... I have duplicated the TestModel.cs from script namespace one into namespace two hoping that it would just match on nicely if I created a new list and passed the object too it, alas no.

What I have tried so far:

IEnumerable e = data as List<TestModel>; //Returns 0 rows
IEnumerable list = (IEnumerable)data; // returns all rows, type System.Collections.IEnumerable {System.Collections.Generic.List<ST_a048e0de86e1432d8da6f60b5d7055db.TestModel>}
List<TestModel> listtest = ((TestModel[])data).ToList()  // Runtime error
List<TestModel> listtest2 = list.Cast<TestModel>().ToList(); //Runtime error - Unable to cast type 'ST_a048e0de86e1432d8da6f60b5d7055db.TestModel' to type 'SC_0573a66ec6c0486a98ee00cea4365654.TestModel'

My end goal is that I need something I can loop through and manipulate into an object SSIS can digest. That part is easy but getting it to loop is proving very difficult!

Extra Note: SSIS Packages are really annoying with dependencies so really looking to avoid using anything special. Also the name spaces are 100% isolated from on another no communication between the two is possible.

Try using Enumerable.OfType Method (IEnumerable)

 List<TestModel> list = ((IEnumerable)data).OfType<TestModel>().ToList();

UPDATE:

IEnumerable list = (IEnumerable)data;

foreach(var testModel in list)
{
    // manipulate testModel into an object SSIS can digest
}

You could try using AutoMapper to map your TestModel classes to each other. It's easy to setup and use.

This is off the top of my head so it might need tweaking, but the code would look very similar to this:

var config = new MapperConfiguration(cfg => {
    CreateMap<ST_a048e0de86e1432d8da6f60b5d7055db.TestModel
              , SC_0573a66ec6c0486a98ee00cea4365654.TestModel>();
    cfg.AddProfile<testModel>();
});

var mapper = config.CreateMapper();    

Then you could convert the listTest using the mapper like this:

var convertedList = mapper.Map<ST_a048e0de86e1432d8da6f60b5d7055db.TestModel>
                  , IList<SC_0573a66ec6c0486a98ee00cea4365654.TestModel>>(listTest);

EDIT: Attempt 2

You said you tried moving the TestModel class to the second namespace. If not you may need to add it in or something equivalent. Then it might be as simple as trying this:

var listTest = data.Select(x => new TestModel 
                       { property1 = x.property1,
                         property2 = x.property2
                         //etc...
                         }).ToList();

That should give you a new List<TestModel>

I wanted to expand on John Ephraim Tugado's solution since it seemed a little incomplete

public void Main()
{
    try
    {
        List<TestModel> testModelList = BuildObjectList();

        TestModel testModel = new TestModel();

        testModel.prop1 = "new prop";
        testModel.prop2 = true;

        testModelList.Add(testModel);

        //Now that we have a testModelList in the correct local class we can 
        //modify it and load it back into the globally held variable for 
        //another Component to use

        Dts.Variables["User::myObjectList"].Value = testModelList;

        Dts.TaskResult = (int)ScriptResults.Success;
    }
    catch
    {
        Dts.TaskResult = (int)ScriptResults.Failure;
    }
}

private List<TestModel> BuildObjectList()
{
    try
    {
        List<TestModel> RunningList = new List<TestModel>();
        TestModel localModel = new TestModel();

        var data = Dts.Variables["User::myObjectList"].Value;
        IEnumerable enumDataList = (IEnumerable)data;

        foreach (var currentObj in enumDataList)
        {
            localModel = GetSingleResult(currentObj);
            RunningList.Add(localModel);
            localModel = new TestModel();
        }
        return RunningList;
    }
    catch
    {
        return new List<TestModel>();
    }
}

private TestModel GetSingleResult(object currentObj)
{
    try
    {
        TestModel returnedResult = new TestModel();

        PropertyInfo[] properties = currentObj.GetType().GetProperties();
        foreach (PropertyInfo pi in properties)
        {
            switch (pi.Name)
            {
                case "prop1":
                    returnedResult.prop1 = pi.GetValue(currentObj, null).ToString();
                    break;
                case "prop2":
                    returnedResult.prop2 = Convert.ToBoolean(pi.GetValue(currentObj, null));
                    break;
                default:
                    break;
            }
        }

        return returnedResult;
    }
    catch {
        return new TestModel();
    }
}

internal class TestModel
{
    internal string prop1 { get; set; }
    internal bool prop2 { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM