views:

359

answers:

4

When I examine the .Columns property of one of my business entities I had missing values for Table and PropertyName. I get the right count of records back from things like Take(5) but all 5 objects will be full of empty strings and 0 values.

Just tried it with another SQL connection and same thing? Where should I start troubleshooting this?

ADDITIONAL INFO and CODE:

// Replacing the CleanUp function seems to be cause
// What am I doing here that is not allowed?
// I'm dealing with Table names like USER_DETAILS and would prefer UserDetail  
// rename standard CleanUp to CleanUp2 then paste this into Settings.ttinclude
string CleanUp(string tableName)
{
 string res = tableName;
 //capitalization
 char[] ca = res.ToLower().ToCharArray();
 for (int i = 0; i < ca.Length; i++) {
   if ((i == 0) || (ca[i - 1] == '_')) {
            ca[i] = char.ToUpper(ca[i]);
   }         
 }
    res = new string(ca);
    //strip underlines
    res = res.Replace("_","");
 //strip blanks
 res = res.Replace(" ","");
 return res;
}

SOLVED (sort of): Looks like it is the removal of the underlines that causes everything to go south. Rob, any chance this could work in a later version? I'd be glad to help if you could point me in the right direction in the source.

+2  A: 

If you can post your CREATE sql for one of your tables - that would be a way to get started. Also - make sure you have primary keys, etc.

Rob Conery
I do have primary keys. Not sure what you mean by CREATE sql. The DDL statement to create the table? I am using this against Legacy databases, where the table structures will hardly change. What's the best way to find the CREATE sql you are looking for? looping through .Columns property?
tyndall
If you're using sql server management studio you can simply right click the table and choose 'Script table as'->'CREATE TO'->'New Query Window'
Adam
But I'm working with a pre-existing database. Anything special you need to do in these circumstances to get things up and running?
tyndall
Ok. I have no idea what I changed, but now its working on both databases. I'm completely baffled.
tyndall
Oh wait... I can recreate it. If I modify my CleanUp function I can reproduce. I'll post this into the question.
tyndall
See last comment to Jim W. tried to post to the thread on GitHub. But GitHub seems broken. I'm behind nasty proxy/firewall/filter so that may be the issue.
tyndall
+2  A: 

Just to note, I think this is the same as issue #107 that I ran into last week. http://github.com/subsonic/SubSonic-3.0/issues#issue/107

Jim W
+1 Have you dug more into this? I got lost in the weeds stepping through the code today, but I think I tracked it down to some Load() method. I haven't taken it past that. Does this need further research? Like I said in other comments I'm willing to help out. But I'm only into SubSonic for maybe 4 weeks now. Don't know a hella of alot about the internals yet.
tyndall
I haven't looked too far into this, but I also think it's related to the property names that get renamed during the CleanUp method changes you've made. I made the similar changes (removing underscores, using pascal case) and ran into the same problem. The fields that didn't get renamed (didn't have a underscore) worked, but the fields that had an underscore and it was removed, didn't load. I think there's a reference to using the modified name in the DataReader instead of the real field name (or vice versa).
Jim W
tyndall
That's the same place that my initial digging lead me to. There object loads its columns from that datareader, but somewhere it's trying to map original column names to modified property names instead of mapping original column names to orignal column names.
Jim W
A: 

Hi Tyndall, I've just applied your CleanUp function within my SubSonic3 Templates. It works just fine. But before do that, I made some patches within Subsonic Core to communicate between Subsonic objects and table column.

  • First, I tried to gather which columns that will be projected (ExecutionBuilder.cs - line 217) then add it into list of string
  • Pass that list into QueryCommand so the QueryCommand object knows which column that will be projected (ExecutionBuilder.cs - line 233)
  • Make some modification in DbQueryProvider.cs (line 297), so DataReader will pass list of column names
  • Finally DataReader will insert value from database according to order in list of string that passed before (Database.cs line 158)

You can look details what I'm doin in here.

Funky81
A: 

After running through the code base I think I've identified an easier solution (IMHO).

The IColumn interface has a 'PropertyName' property defined which I believe is designed to indicate the name of the property representing this column on the table class (akin to the 'ClassName' property on ITable). In the Structs.tt template this is not set so I have set it (circa line 39) to the value of the columns CleanName property.

This then allows the GetColumnByPropertyName method in DatabaseTable.cs (circa line 110) to use the PropertyName as opposed to using the Name.

I've added the Name property to the IColumn interface as it seemed to be an oversight, which then means that the Load extension method (Database.cs circa line 143) can be amended to access the Columns property of the passed in object (if it is a derivative of IActiveRecord) and use that to map the 'Name' to the 'PropertyName'.

If I can get the time to figure our GitHub I'll submit the changes.

Cheers

Gary

G McCormack
Cool. I think others have looked at this since I originally posted. You may want to see what other info is out there about this. If not GitHub maybe you can email them the code to add. (I'm sure people hate that...)
tyndall
Oh. and good info +1
tyndall