1

I've been searching and playing around with GetType() for a while, but I keep getting the name of the column (which I already have) and not the value.

I'm trying to build a csv file from the results of a method (stored procedure call) in a datacontext.

I'm fine up to figuring out how to dynamically grab result.some_column_name from the result set.

using (SomeDataContext ctx = new SomeDataContext())
        {
        List<Some_MethodResult> results = ctx.Get_Some_Method(parameter1, parameter2, parameter3).ToList();

        var colnames = ctx.Mapping.MappingSource.GetModel(typeof(SomeDataContext)).GetMetaType(typeof(Get_Some_MethodResult)).DataMembers;


        foreach (Get_Some_MethodResult r in results)
        {
            foreach (var colname in colnames)
            {
                string line = "\"" + r.GetType().GetField(colname.Name).ToString() + "\",";
                sb.Append(line);
            }
         }

The above gets me the name of the field, and I'm looking for the value. GetMember() doesn't seem to get me any better results.

I'm still looking to see if I can find out the right way to dynamically refer to a column by column name, but if this is simple and just a non-often-asked question, I'm hoping someone can point me in the right direction.

2 Answers 2

2

Save the result of GetField and call GetValue on it, passing r as the parameter.

But you don't want to be calling GetField inside a nested loop. Loop through the columns once, saving all the GetField() results into a FieldInfo[] array. Then inside your nested loops, fetch from the array.

If that isn't performant enough, you can use an expression tree to build a Func<Get_Some_MethodResult, object> from each field that accesses that field on any arbitrary object, and save an array of those instead of FieldInfo. (For properties, this was possible using GetGetMethod and CreateDelegate before expression trees). Then you wouldn't need any reflection at all inside the nested loops.


Of course, all of this complexity might be avoided if you skipped over your ORM mapping and just processed the IDataReader that came back from the stored procedure. A data reader provides easy indexed access to both column values and values.

It's really quite trivial to write a function that turns any IDataReader into CSV.

Sign up to request clarification or add additional context in comments.

2 Comments

Close, but no cigar. GetField wasn't the place I should have been looking, apparently. I'll add my answer shortly.
@adrianstovall: In your question, you said you did get the name back from GetField(colname.Name).ToString(). Are you now saying that the code in the question did NOT get the name?
1

So, the answer has a couple of parts to it. Kudos to my co-worker Tony Colich for helping me learn on this one.

First, it's GetProperties() and not GetFields() that I should have been looking at for the column values returned by the sproc.

Knowing that helped immensely. The new loop looks like (please ignore the colval/boolean bit):

using (SomeDataContext ctx = new SomeDataContext())
        {
        List<Some_MethodResult> results = ctx.Get_Some_Method(parameter1, parameter2, parameter3).ToList();

        var colnames = ctx.Mapping.MappingSource.GetModel(typeof(SomeDataContext)).GetMetaType(typeof(Get_Some_MethodResult)).DataMembers;

        var props = typeof(Get_Some_MethodResult).GetProperties().Where(p => colnames.Any(n => p.Name == n.Name));

        foreach (Get_Some_MethodResult r in results)
        {
            foreach (var colname in colnames)
            {
                bool firstcol = true;
                foreach (var colname in colnames)
                {
                    var prop = props.FirstOrDefault(p => p.Name == colname.Name);
                    if (prop != null)
                    {
                        string colval = "";
                        if (!firstcol)
                        {
                            colval = ",\"" + prop.GetValue(r, null).ToString() + "\"";
                        }
                        else
                        {
                            colval = "\"" + prop.GetValue(r, null).ToString() + "\"";
                        }
                        //var field =
                        sb.Append(colval);
                        firstcol = false;
                    }
                }
                sb.AppendLine();
            }
         }

Now, as far as whether or not I should have done this at all, there are only so many hours to spend on a project sometimes, and this was the path of least resistance. Thanks to all who responded!

1 Comment

You really should use GetGetMethod() which I mentioned in my answer, and do that outside the nested loops (GetProperties() and GetGetMethod() need reflection which is very expensive). Do it just once, and then reuse the getter method on each successive row of results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.