1

I am using DapperLite, a port of Dapper, for use in Compact Framework. I get an ArgumentException, no other info in the below method at the specified line of the SqlMapper.cs file.

Really struggling with what to look for next or what's actually broken.

/// <summary>
    /// Populate a references type from an IDataRecord by matching column names to property names.
    /// </summary>
    private static void PopulateClass(object objectClass, IDataRecord reader)
    {
        Type theType = objectClass.GetType();
        PropertyInfo[] p = theType.GetProperties();


        // Only set properties which match column names in the result.
        foreach (string columnName in GetColumnNames(reader))
        {
            string colName = columnName;
            object value = reader[colName];
            PropertyInfo pi = p.FirstOrDefault(x => x.Name == colName);


            if (pi == null || value == DBNull.Value) continue;


            Type columnType = value.GetType();
            Type actualType = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType;


            // Check for a directly assignable type
            if (actualType == columnType || actualType == typeof(string) || actualType == typeof(int))
            {
                // Error generated here
                pi.SetValue(objectClass, value, null);
            }
            else
            {
                value = actualType.GetMethod("Parse", new[] { typeof(string) }).Invoke(null, new[] { value });
                pi.SetValue(objectClass, value, null);
            }
        }
    }

The values at that point are objectClass = Models.Employee and value=1. The colName, from further up in the Method, is Id which is an int in the Employee model.


Added Employee Model based on Comment:

namespace BioPadPunchClock.Models
{
    public class Employee
    {
        public int Id { get; set; }
        public int CDB_Employee_PK { get; set; }  //Employee PK in the Central DB. If .null., new emp record on this timeclock needs to be pushed to the CDB.
        public string Name { get; set; }
        //public string FaceImage { get; set; }  //path to Jpeg image 136x90 pixels .\NAND\pictures\  named as <pk>.jpg
        public DateTime? BirthDate { get; set; }
        public string Status { get; set; }  //Full Time – Hourly, Inactive, Terminated, Part Time - Hourly  
        public DateTime? LastPunch { get; set; }
        public string LastPunchDirection { get; set; }  //IN or OUT
        public string PIN { get; set; }  // 4 digit
        public int CardNum { get; set; }  //HID Card Number
        public int CardFacCode { get; set; }  //HID Card Facility Code
        public string FpTemplate { get; set; }  //Fingerprint Template (registered fingerprint)
        public DateTime? LastUpdate { get; set; }  //When this employee record was last sync’d to the CDB. This value will match exactly in the LDB and CDB after a successful sync.
        public int DayTotal { get; set; } // Minutes cumulative for the current day at time of last punch
        public int PayPeriodTotal { get; set; } //Minutes cumulative for the current pay period at time of last punch
        public string Department { get; set; }
        public string SSN { get; set; }
        public bool ShouldPromptDept { get; set; } //Prompt employee to choose department each time
    }
}

Further findings...

When I look at my Model.Employee at that point all of the string properties say Could not evaluate expression with a red exclamation point. Is this a clue or normal?


Further findings...

Not sure if this matters or not but when I step through the code and inspect the values I notice that the actualType == Int32 and the columnType==Int64 while the value it's evaluating is 1.

Not sure that makes any difference since there is a actualType.Equals(typeof(int)) but figured I'd mention it.

Refracted Paladin
  • 12,096
  • 33
  • 123
  • 233
  • According to MSDN, `ArgumentException` can be raised in two cases. Most probably, your case is the second. Does `Employee.Id` have setter at all? – Dennis Jan 08 '14 at 18:18
  • I added my Employee Model to the question but yes, it has a Setter. – Refracted Paladin Jan 08 '14 at 18:23
  • What is exact exception message and argument name? Is there inner exception? – Dennis Jan 08 '14 at 18:36
  • That's just it, there isn't. It's just `ArgumentException was unhadled` and under Details-->Message `ArgumentException`. – Refracted Paladin Jan 08 '14 at 18:42
  • The following... `actualType == typeof(string)` will not work when you try SetValue using a string on that line. How do you plan to assign a string to an int? If it is the string "1" it will throw an `ArgumentException` However, at least on the desktop version, it will throw an informative error message telling you just that. However, it does to be an error in your logic. Also how can you assume that type int will work in the same condition? Also how can you assume the type has a Parse method if it doesn't meet those conditions? – Alan Jan 08 '14 at 20:30
  • When testing types like this, you should use `actualType.Equals(typeof(string))` instead. –  Jan 08 '14 at 23:23
  • Thanks for the tips, I'll look into it. Unfortunately all the suggestions so far are with DapperLite codebase. I had hoped it was me doing something simple and silly... – Refracted Paladin Jan 09 '14 at 16:19
  • Also, for the record, I changed the SqlMapper.cs in DapperLite based on @Amy suggestion and still same result. – Refracted Paladin Jan 09 '14 at 16:23

1 Answers1

1

We figured this out on GitHub with the last piece of information.

Since the columnType is Int64 for the Id column, changing the type of the Id column in the model to Int64 will fix this issue.

Ryan Kirkman
  • 4,051
  • 2
  • 25
  • 20
  • Note that I've changed the way DapperLite populates objects based on suggestions by Alan and Amy: https://github.com/ryankirkman/DapperLite/commit/43f5588ec15c54c8dea40fec15f3a0b5a9a73f07 – Ryan Kirkman Jan 17 '14 at 20:17