Home > Software design >  Get value of DataContext Result column by variable name
Get value of DataContext Result column by variable name

Time:02-04

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.

CodePudding user response:

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.

CodePudding user response:

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!

  •  Tags:  
  • Related