tags:

views:

845

answers:

5

In the database, I have a table called Contact. The first name and other such string fields are designed to use a Char datatype (not my database design). My object Contact maps to a string type in the properties. If I wanted to do a simple test retrieving a Contact object by id, I would do something like this:

Contact contact = db.Contacts.Single(c => c.Id == myId);
Contact test = new Contact();
test.FirstName = "Martin";

Assert.AreEqual(test.FirstName, contact.FirstName);

The contact.FirstName value is "Martin " because of the char type. Where can I intercept the FirstName property when it is being loaded? OnFirstNameChanging(string value) does not get called on the initial load (contact), but does on the test object.

A: 
Contact contact = db.Contacts.Single(c => c.Id.Trim() == myId);

And check that the LINQ provider translates that into the appropriate SQL.

Richard
I don't think the problem was with the Id field.
tvanfosson
+4  A: 

If you can't change the schema, you might want to make the designer generated accessor private/protected and create a public accessor to front-end the property in a partial class implementation. You can then Trim the value in the get accessor.

public partial class Contact
{

    public string RealFirstName
    {
       get { return this.FirstName.Trim(); }
       set { this.FirstName = value; }
    }

    ...
}
tvanfosson
This is a good solution, because not only are the fields a char type, they also are called First_Name. So I could fix all the fields as well, without changing it in my Object designer.
Marsharks
The problem is when I create a query and try to use something like FullName = c.FirstName + ' ' + c.LastName. I was getting the Could not translate expression and could not treat it as a local expression Message.
Marsharks
Once you've done your filtering you could use ToList() to generate the actual query then do your select on the resulting list. Since they are objects at that point the construction of FullName should work.
tvanfosson
I was using a light weight object, not returning a list. Here is the line that was blowing up:ContactName = act.PhoneContact.FirstName + " " + act.PhoneContact.LastName
Marsharks
A: 

You can run a ForEach on your list of contacts before trying to search for Martin.

var contacts = db.Contacts.ForEach(c => c.FirstName = c.FirstName.Trim());
Contact contact = contacts.Single(c => c.Id == myId);
contact.FirstName // = "Martin"

But this way is not very easy to maintain if it has to be done for multiple fields.

Samuel
+1  A: 

It depends on the control you have over the schema and the code.

If the values are being set up by calling a constructor with all parameters, do the trims, etc as they are assigned to the member variables.

If they are being assigned to the properties (probably from the example), change the SET accessor so that it does the trim there.

You do have potential issues if you actually WANT leading or trailing spaces at some point though.

If you can't modify the base class code, try using partial classes, or inheriting from the class and overriding the properties there.

If you can't do that, then my last suggestion would be to write a factory class of some sort that you pass a created object to and it cleans it up per the rules you want.

Roger Willcocks
+2  A: 

Maybe you could put it in the OnLoaded() partial method? Note: I've never used this, but I assume it would look like this:

public partial class Contact
{
    partial void OnLoaded()
    {
        FirstName = FirstName.Trim();
    }
}
Chris Shaffer
This works. Its is fairly easy to do for each field because I am not showing that many fields for display. Thanks.
Marsharks
This is going to generate a property changed event -- which could trigger other actions -- and could result in unnecessary updates to the database since you are changing the value of the property without making any semantic changes to the content.
tvanfosson
The point of the question was to find the place to do such logic (in this case OnLoaded()); The method itself could just as easily consist of "_FirstName = _FirstName.Trim();" to avoid the propery changed event firing.
Chris Shaffer
That is probably a good idea for what I need, since I cannot change the database schema. I really only use this class as a data object to hold the values of a database record. It would be nice if I could have intercepted a property loading event, but I can't.
Marsharks
Be aware that you could use the OnLoad() method only if the corresponding table to this class has a primary key.
Flo