CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

David Hayden [MVP C#]

         .NET Tutorials, Patterns, and Practices


Published by

Comments

TrackBack said:

# February 21, 2005 6:23 PM

Tim said:

For the record my Boy was 10 lbs. 10 oz. 22 1/2 in. But he was also born at 37 1/2 weeks. <grin />
# February 22, 2005 1:04 AM

Raymond Lewallen said:

Great post David. This was something I was planning on covering in the future, but don't think I would have covered it this well. Wonderful explanation on a topic that slightly confused me 3 years ago. Also, that .Net Framework Programming is a great book. I always have it right here handy.
# February 22, 2005 12:01 PM

Brendan Tompkins said:

Agreed! Good Post. I actually did a poor job delving into this a while back, I really didn't understand it at the time:

http://codebetter.com/blogs/brendan.tompkins/archive/2004/07/09/18700.aspx

Which solicited this statement from none other than Raymond Chen:

"The hash function must return exactly the same value regardless of any changes that are made to the object."

Since you're using your ID (which shouldn't change) for your hashcode, you're doing things right. I think. :)
# February 22, 2005 12:51 PM

Angelos Petropoulos said:

Have a read of my post on GetHashcode(), Equals(object obj) and the '==' operator.

http://blogs.wdevs.com/angelos/archive/2004/12/21/1553.aspx
# February 24, 2005 5:11 AM

TrackBack said:

# February 24, 2005 1:58 PM

TrackBack said:

# February 24, 2005 2:00 PM

TrackBack said:

# February 24, 2005 2:23 PM

Brendan Tompkins said:

This is cool David! Nice explanation.

I use format strings all the time and love them... I would do the extra work of overriding ToString, if I could use them along with a custom format string. I guess I could just try formatting with the custom string if I don't get one of the expected values, or if I find curly braces. Would that be how you would do it?

Also, I wonder if there would be a clever way, using attributes or something, where you could be more specific about what values you accept in your ToString. I've always hated this... I mean, "G", we use it all the time, but what's that all about? How about something more strongly typed?

Not being nitpicky, but in case you missed this, you don't have to ToString() any of your non-string obejcts passed to String.Format, so this works just as well, and less typing:

string.Format("{0} {1} Age= {2}",_firstname,_lastname,_age);
# February 24, 2005 4:41 PM

David Hayden said:

Hey Brendan,

In the example above I overloaded ToString a couple of times for flexibility. You can use the overloaded method ToString(string format) to format the person using a given format string.

You could use attributes to help generate documentation. I typically add this type of information in comments so NDoc can add it to the documentation. If you want something during runtime, a possible solution would be to have the "default" in the switch statement as well as the override of ToString() output a list of possible format strings as well as a description of each. You could certainly just reflect on the attributes at runtime.

String.Format is expecting an Object and _age is a value type. If I just pass in "_age", I have to deal with issues of boxing. Better to pass "_age.ToString()" beforehand and you save the performance hit.
# February 24, 2005 6:04 PM

TrackBack said:

# February 24, 2005 6:11 PM

Brendan Tompkins said:

I do way too much skimming when I read blogs *blush*

"If I just pass in "_age", I have to deal with issues of boxing."

I didn't know this. I need to learn more about boxing and it's preformance issues. Perhaps a post on boxing would be a good one for a CodeBetter blogger to tackle..

# February 25, 2005 7:39 AM

Raymond Lewallen said:

Brendan, this is why in my post about MSIL, I mentioned that when you understand what your code is doing in MSIL, you write better code :) If you look at the IL, you'll see the boxing instruction for the _age without the ToString(). I am actually working on a post on boxing and unboxing to go up late next week after the final OOP polymorphism post.
# February 25, 2005 10:40 AM

TrackBack said:

# February 25, 2005 12:17 PM

TrackBack said:

# February 25, 2005 12:30 PM

TrackBack said:

# February 25, 2005 12:43 PM

Raymond Lewallen said:

Awesome post, David. I'll definately be referring people back to here first for the boxing portion, and I'll cover the unbox/copy operations. I'll add some hard numbers on the performance hits involved and garbage collections that may occur because of the heap allocations, and provide some CLR profiler graphs to make things pretty :) I'll probably put the post up on Monday. Jeffery Richter's book absolutely does a great job of explaining the processes.
# February 25, 2005 3:17 PM

Sahil Malik said:

Damn this is good !!
# February 26, 2005 10:29 PM

TrackBack said:

# February 27, 2005 9:18 AM

TrackBack said:

# February 27, 2005 9:18 AM

TrackBack said:

# February 27, 2005 9:22 AM

TrackBack said:

# February 27, 2005 9:22 AM

TrackBack said:

# February 27, 2005 9:29 AM

TrackBack said:

# February 27, 2005 9:29 AM

TrackBack said:

# February 27, 2005 11:14 AM

TrackBack said:

# February 27, 2005 11:35 AM

TrackBack said:

# February 27, 2005 12:27 PM

Brendan Tompkins said:

This is good to know. I almost always use a foreach, unless I'm modifying the collection somehow within the loop, which throws runtime errors.
# February 27, 2005 1:50 PM

Brendan Tompkins said:

Cool stuff, David!

A while back I posted a CollectionView class that allows you to add sorting to any property of your collection objects.

It's not a perfect solution though, sub obejcts are not handled well, as is multiple propery sorting. Check it out here:

http://codebetter.com/blogs/brendan.tompkins/archive/2004/09/02/24116.aspx
# February 27, 2005 1:57 PM

Brendan Tompkins said:

I second that, Sahil. I'm so embarrased to admit it, but I wasn't exactly sure how boxing worked until I read this. Thanks, David!
# February 27, 2005 2:53 PM

TrackBack said:

# February 27, 2005 4:25 PM

TrackBack said:

# March 1, 2005 8:07 AM

TrackBack said:

# March 1, 2005 8:10 AM

TrackBack said:

Blog tools for Alt. IDE's setup and some JS Native Object Expansion
# March 1, 2005 8:19 AM

TrackBack said:

# March 1, 2005 2:36 PM

.Net Adventures said:

Check out this article "FormattableObject an Aggregating reflection-based ToString() implementation" by Scott Hanselman
: http://www.hanselman.com/blog/PermaLink,guid,2a0fdc2c-6b15-4a46-a802-0ebc0b8662d9.aspx
# March 1, 2005 3:04 PM

TrackBack said:

# March 1, 2005 3:13 PM

TrackBack said:

# March 1, 2005 4:10 PM

Eric Wise said:

Now here is something I'd been thinking about playing with for quite some time but never got around to doing it. Great post David!
# March 1, 2005 6:47 PM

TrackBack said:

# March 2, 2005 9:55 AM

TrackBack said:

# March 2, 2005 10:31 AM

Sam said:

Wow that's ugly. :)
# March 2, 2005 3:08 PM

TrackBack said:

# March 2, 2005 5:18 PM

Sam said:

Ok, that was kinda a crappy comment, but I was leaving work. :)

What don't I like about this? Well, it really has nothing to do with configuration, so I think the name is misleading. Serialization can get ugly pretty fast for configuration files though. No defaults. Look at the encrypt attribute for example. Why does that even need to be there?

Instead you could write an XmlActivator that takes in an XmlDocument and returns you an instance based on Type specified in the document. Basically your document would look pretty much like sitesettings.config, except with the root tag have the type attribute. Then you can get rid of the xmlSerializerSection and SiteSettings sub elements. Like so: (here's hopin' this works)

&lt;SiteSettings type="SiteSettings, configtest"&gt;
&lt;Name&gt;DavidHayden.com&lt;/Name&gt;
&lt;Url&gt;http://www.davidhayden.com/&lt;/Url&gt;
&lt;EmailAddress&gt;nospam@nospam.com&lt;/EmailAddress&gt;
&lt;/SiteSettings&gt;
&lt;/code&gt;&lt;/pre&gt;

You pass this into your XmlActivator, it parses it out (in a version a friend recently wrote you could also specify the Type for each parameter, or it would default to string if the attribute was not present though this could also be inferred from the parameter Type through reflection), and uses System.Activator to give you an instance.

This doesn't do the same thing though you might say. You're right. If you want to be able to specify a different xmldocument through app.config, you're also going to need to write a configurationSectionHandler. There lots of examples on the web, and it's actually a whole lot easier than I thought before I wrote one, so don't worry, if I can do it anyone can. :) Instead of all that nasty markup though, you only need your section element specifying the handler to use, and the element named in the section element. That element only needs to contain two attributes: A name for the instance, and the path to the xmldocument. Sure you could add encryption and all that, but I'd recommend you do it manually. Parsing Xml is actually really easy, and it lets you do things like default to no encryption if the attribute is missing.

With this sort of design, for the same example, your xml files would be half the size, and you'd get the same functionality and more.

The config app block could allow other stuff I'm not seeing here, so this is just based on what I see. I'm not familiar with it personally. But from the example it looks like the hard way to do it.

That's my 2c anyways. :)
# March 2, 2005 9:02 PM

Sam said:

Resharper's the best thing that's ever happened to .net. :) I like it so much I'm swearing off the sweetness of generics until Resharper supports VS2K5.
# March 2, 2005 9:05 PM

David Hayden said:

You're absolutely right, Sam. If you plan on always persisting your objects to XML, then certainly the Configuration Application Block is overkill and we can build a similar solution that requires less configuration settings and can output less XML.

The application block provides a bit more functionality, however, than what I have mentioned. The "Encrypt" attribute is necessary, because you can actually specify and create your own encryption algorithms. I assume they would need this attribute to know when to encrypt and decrypt the information.

The application block also allows you to create and specify other storage providers and data transformers. It happens to come with XML-based solutions now, but you can certainly roll your own solutions to work with a database, etc. The hope is that others will also roll their own solutions and we could share efforts. The code in your application would stay the same and all you would do is make modifications to the config file specifying the new storage providers and data transformers.

The application block will also fire off events if changes occur to the underlying storage provider so you can reload any changes in your application.

Then you have the warm-and-fuzzy benefits that may or may not interest some people. Such as the fact that the solution is community supported and thus will have bug fixes and come out with new enhancements as time goes on (we hope!). From an employer's perspective, it also makes it easier to swap out developers and contract out work if code isn't so much developer or company specific, but more standard in nature.

All-in-all, however, your comments are valid. Sometimes these application blocks can be overkill and if one has a good solution already in-house, this may not be the way to go. However, for those people who don't have a solution and can't or don't have time to write a solution themselves, it took me all of about 30 minutes to get this running.
# March 3, 2005 6:57 AM

TrackBack said:

# March 3, 2005 5:44 PM

TrackBack said:

# March 3, 2005 5:44 PM

TrackBack said:

# March 3, 2005 6:33 PM

TrackBack said:

# March 3, 2005 6:33 PM

The Dev Theologian said:

Catching up..
# March 3, 2005 11:53 PM

Nate said:

First, thanks for the great stuff every day David.

Would you use this method for setting storage in an ASP.NET application over the web.config file? If so, why? Advantages/disadvantages?
# March 4, 2005 5:28 AM

David Hayden said:

Hi Nate,

The only "gotcha" about web.config is that changing it causes a restart of the application. You really don't want global settings in web.config that change often and don't require an application restart. If you are essentially adding settings to web.config that rarely or never change, that is fine. Volatile settings should be tossed in an XML file or database, depending on your application needs.

The application block is cool, but could be overkill for smaller applications. I tend to use separate XML files and my own serialization which I showed in a separate post. You can add the global settings to the cache with a dependency on the XML file to remove it from the cache when a change is detected. This is part of my web page inheritance model that I will toss up sometime this weekend I hope. It is pretty basic and gives you another option for your web applications.
# March 4, 2005 8:06 AM

TrackBack said:

# March 4, 2005 9:38 AM

TrackBack said:

# March 4, 2005 9:41 AM

TrackBack said:

# March 4, 2005 11:20 AM

TrackBack said:

# March 4, 2005 11:23 AM

TrackBack said:

# March 4, 2005 11:23 AM

TrackBack said:

# March 5, 2005 1:48 PM

TrackBack said:

# March 5, 2005 1:58 PM

TrackBack said:

# March 5, 2005 1:58 PM

TrackBack said:

# March 6, 2005 12:32 PM

TrackBack said:

# March 6, 2005 12:39 PM

TrackBack said:

# March 6, 2005 12:42 PM

Joel Ross said:

Thought you might be interested to see this:

http://www.rosscode.com/blog/index.php?title=generic_multiple_sorting_for_typed_colle&more=1&c=1&tb=1&pb=1

This is a generic way to sort on any column of any object using reflection.
# March 6, 2005 4:23 PM

TrackBack said:

# March 6, 2005 5:48 PM

TrackBack said:

# March 6, 2005 5:48 PM

TrackBack said:

# March 6, 2005 5:49 PM

TrackBack said:

# March 6, 2005 5:49 PM

TrackBack said:

# March 6, 2005 5:53 PM

TrackBack said:

# March 6, 2005 5:53 PM

TrackBack said:

# March 6, 2005 6:05 PM

TrackBack said:

# March 6, 2005 6:08 PM

TrackBack said:

# March 6, 2005 6:08 PM

TrackBack said:

# March 8, 2005 8:04 AM

TrackBack said:

# March 8, 2005 8:08 AM

TrackBack said:

# March 8, 2005 8:08 AM

TrackBack said:

# March 8, 2005 8:26 AM

TrackBack said:

# March 8, 2005 8:26 AM

TrackBack said:

# March 8, 2005 9:36 AM

TrackBack said:

# March 8, 2005 9:37 AM

TrackBack said:

# March 9, 2005 6:35 AM

TrackBack said:

# March 9, 2005 6:35 AM

TrackBack said:

# March 9, 2005 6:35 AM

TrackBack said:

# March 9, 2005 7:41 PM

TrackBack said:

# March 9, 2005 7:41 PM

TrackBack said:

# March 9, 2005 7:55 PM

TrackBack said:

# March 9, 2005 7:55 PM

TrackBack said:

# March 9, 2005 9:39 PM

TrackBack said:

# March 9, 2005 9:39 PM

TrackBack said:

# March 9, 2005 9:54 PM

TrackBack said:

# March 9, 2005 9:54 PM

Jeffrey Palermo said:

Awesome. Sample code that could actually be used. Thanks for your post. It illustrates, also, how to use a data class to populate business objects.
# March 10, 2005 8:11 AM

TrackBack said:

# March 10, 2005 9:52 AM

TrackBack said:

# March 10, 2005 9:56 AM

Josh Flanagan said:

It is a nice abstraction, no question.

Unfortunately, the query and the parameter syntax in your example ARE specific to SQL Server.

For example, if you change your configuration to use the OracleClient provider, you will still have to change the query in your code to something like:

Select * from Customers Where CustomerID = :CustomerID

If you use an OLEDB provider, it becomes:

Select * from Customers Where CustomerID = ?

I am assuming the Enterprise library does not do this translation of the query for you. You still have to change the query yourself. If EL does handle it, then cool.
# March 10, 2005 10:34 AM

Anand Kakde said:

Simple yet effective post David. Thank you.

Can we take a step further about how to set up the objects (Dos and Don’ts) effectively based on your following comment:
{There are some gotchas about how you need to set up your objects, how deeply XML serialization will "copy" your objects, etc., but that is out of the scope of this article.}
# March 10, 2005 10:47 AM

TrackBack said:

# March 10, 2005 11:23 AM

David Hayden said:

Thanks, Jeffrey.
# March 10, 2005 1:42 PM

David Hayden said:

Josh,

You're absolutely right.

If you end up hardcoding sql you won't be as abstract as you might like. I would have to peek at the source code to be sure, but I doubt very much that Enterprise Library does any sort of translation. Great comment.
# March 10, 2005 1:49 PM

Josh Flanagan said:

After I made the comment, I started to think that maybe EL *does* do the translation for you - thinking it might be pretty easy with some regex replace calls. But as I started to think about the different scenarios, I realized it would be pretty difficult. The killer is the OLEDB case which doesn't allow for named parameters. If you had a query that only took a single parameter, but used it twice within the query: for Oracle and Sql, you only add a single Parameter to the Command object. For OleDB, you would have to add 2 Parameters to the Command object - both with the same value.
Even storing the SQL query in a configurable location (as opposed to hardcoded) wouldn't help, since the number of parameters differs based on provider, so your code would have to change accordingly. Does EL allow you to define the number & type of parameters for a string query in your config file?
I wonder if you have to use stored procedures if you want true abstraction from the database provider.
# March 10, 2005 2:01 PM

Marsha said:

If the configuration section - i.e. SiteSettings encrypt property is set to encrypt=true in EL Configuration Console will the storage provider file be encrypted? When "SiteSettings" encrypt is set to true, I keep getting System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid error even though the File Key Algorithm Storage Provider is configured. And the .config file is not encrypted. Thanks.
# March 10, 2005 4:28 PM

TrackBack said:

# March 11, 2005 9:00 AM

TrackBack said:

# March 11, 2005 9:06 AM

TrackBack said:

# March 11, 2005 9:08 AM

David Hayden said:

I think you're right, Josh. If you want true abstraction, you will need to go the stored procedure route.

The config file does not have the flexibility now of allowing you to specify the number and types of parameters for string queries.

I took a brief look at the code last night and there is a ParameterToken field defined as "@" for SqlServer and ":" for Oracle just as you mentioned. You could probably override it and do some clever coding to make these string queries more flexible and less dependant on the database, but I don't think we should go there :)

In most cases, people probably tend to use the DAAB to write less code and for API consistency as opposed to database abstraction, but you bring up a good point about how stored procedures appear to be more ideal if you really want the ultimate abstraction.
# March 11, 2005 10:41 AM

David Hayden said:

For the sake of this example, you just need to make sure you have a public read/write property for each private field so that all your settings get serialized and that you have a default public constructor (which c# implicity created for me in this case but I recommend explicity creating one).

As far as a more advanced article on XML Serialization, I hadn't planned on writing anything in the near future. You can probably Google for some advanced articles in the meantime.
# March 11, 2005 10:56 AM

TrackBack said:

# March 11, 2005 11:08 AM

TrackBack said:

# March 11, 2005 11:08 AM

Jeff Lynch said:

Dave,

How do you get the cool little "boxes" around your sample code man?
# March 11, 2005 2:59 PM

David Hayden said:

Those are the Fieldset and Legend HTML Tags.

I don't think I can shown the tags well via this comment area so check here for an example:

http://www.w3.org/TR/REC-html40/interact/forms.html#edef-LEGEND
# March 11, 2005 3:20 PM

TrackBack said:

# March 11, 2005 6:21 PM

TrackBack said:

# March 11, 2005 6:21 PM

TrackBack said:

# March 11, 2005 6:21 PM

TrackBack said:

# March 11, 2005 6:33 PM

Mark Bonafe said:

A good explanation of the DAAB. I never liked all the reflection, though. Why not just create methods to create what is need without the reflection? Sure, it's a little more code, but it's much more effecient than using reflection.
# March 14, 2005 5:57 AM

David Hayden said:

I am not sure how they can dynamically create an instance of a class they don't know until runtime without using reflection.

You're right that they don't need reflection if they are only ever going to have two database providers: SqlDatabase and OracleDatabase.

However, I think the PAG wanted to leave the opportunity for others to either override the existing classes o