Graeme Hill's Dev Bloghttp://graemehill.caMy random thoughts on software developmentMon, 04 Feb 2013 06:29:51 GMTPyRSS2Gen-1.1.0http://blogs.law.harvard.edu/tech/rssEFTracingConnection and CreateDbCommandhttp://graemehill.ca/eftracingconnection-and-createdbcommandI've been using the EFTracingConnection class that comes as a part of the Entity Framework Provider Wrappers project. It works wonderfully well for tracking the SQL queries that get executed with the Entity Framework DbContext but I ran into a snag when I combined it with the EntityFramework.Extended library for batch operations. I started getting a NotSupportedException whenever I tried to execute a batch operation with the tracing connection enabled. It turns out the EntityFramework.Extended internally uses DbConnection.CreateDbCommand() to run its SQL. However, the EFTracingConnection implementation does not implement that method since it acts as a wrapper for DbConnection even though it also inherits from it (ie: EFTracingConnection has a DbConnection even though it also is a DbConnection). The fix is to make a subclass of EfTracingConnection and implement the method by invoking it on the wrapped object: public class MyTracingConnection : EFTracingConnection { protected override System.Data.Common.DbCommand CreateDbCommand() { return this.WrappedConnection.CreateCommand(); } } So far this seems to work like a charm. http://graemehill.ca/eftracingconnection-and-createdbcommandSun, 03 Feb 2013 00:00:00 GMTC++ const correctness beats the .NET/Java alternativeshttp://graemehill.ca/c-const-correctness-beats-the-netjava-alternativesThe C++ const keyword is a powerful tool. It basically allows you to pass a pointer or reference that can only be used to call const methods. ie: You can implement a mutable class and then pass an immutable reference to that class (the keyword also does other things, but that's not what I'm writing about). This defines a much stronger contract. When a function asks for a pointer to an instance of Foobar it can promise that it will not change that object. For example ...http://graemehill.ca/c-const-correctness-beats-the-netjava-alternativesSat, 03 Dec 2011 00:00:00 GMTExporting armature animation with the Blender 2.5 Python APIhttp://graemehill.ca/exporting-armature-animation-with-the-blender-25-python-apiIt took me forever to get this right so I thought I'd post my solution. Most of the examples I found were for previous versions of Blender (the API changed a lot in Blender 2.5). The sample scripts I did find never seemed to work and the official documentation seemed to be somewhat insufficient ...http://graemehill.ca/exporting-armature-animation-with-the-blender-25-python-apiThu, 27 Oct 2011 00:00:00 GMT.NET reflection: don't rely on the call stack, it's a trap!http://graemehill.ca/net-reflection-dont-rely-on-the-call-stack-its-a-trapIn recent memory I have twice tried to write reflection code that seemed totally badass at the time but turned out to be just plain bad. One case involved the use of GetCallingAssembly() and the other involved navigating the stack trace with stackTrace.GetFrame(1). While there is nothing inherently wrong with these functions (ie: they can be used perfectly fine for logging or debugging) you absolutely cannot depend on a specific result due to runtime optimizations by the .NET JIT compiler. For example ...http://graemehill.ca/net-reflection-dont-rely-on-the-call-stack-its-a-trapWed, 26 Oct 2011 00:00:00 GMTAre you sure you want List? Maybe you really want HashSethttp://graemehill.ca/are-you-sure-you-want-list-maybe-you-really-want-hashsetI often find that I get so used to using ListT for my collections that I forget to consider whether it is really the right tool for the job. If the collection is not ordered, and you don't want duplicates then there are a lot of benefits to using HashSetT. For example with ListT you'll find yourself writing code like this: ...http://graemehill.ca/are-you-sure-you-want-list-maybe-you-really-want-hashsetSun, 06 Feb 2011 00:00:00 GMTConverting from svn to git: another reason not to use external referenceshttp://graemehill.ca/converting-from-svn-to-git-another-reason-not-to-use-external-referencesUsually it is easy to import a subversion repository into git. You just do this ...http://graemehill.ca/converting-from-svn-to-git-another-reason-not-to-use-external-referencesWed, 03 Nov 2010 00:00:00 GMTThe trouble with propertieshttp://graemehill.ca/the-trouble-with-propertiesProperties are supposed to provide encapsulation for your getter and setter logic, but they really don't enforce it. Here's what I mean ...http://graemehill.ca/the-trouble-with-propertiesFri, 01 Oct 2010 00:00:00 GMTA lesson on using closed source librarieshttp://graemehill.ca/a-lesson-on-using-closed-source-librariesA challenging question that programmers are often faced with when chosing a library is whether to go with an open source option or a closed source product that may come with professional support. The answer of course is "it depends" and the quality of each library will often be more important than whether or not it is open source. In the past I have not concerned myself too much with whether or not the source code is available to me because I normally don't plan on ever touching it. I don't use an existing library because I want to spend weeks digging through source code and internals, I use them because I don't want to spend much time on that feature. I want it to just work ...http://graemehill.ca/a-lesson-on-using-closed-source-librariesSat, 19 Jun 2010 00:00:00 GMTLINQ queries return queries not datahttp://graemehill.ca/linq-queries-return-queries-not-dataThe title of this article is a pretty obvious statement, but it's actually pretty easy to forget and it can lead to some painful bugs. Here's a code snippet whose output may seem surprising ...http://graemehill.ca/linq-queries-return-queries-not-dataWed, 19 May 2010 00:00:00 GMTVisual Basic 10 properties still lag behind C#http://graemehill.ca/visual-basic-10-properties-still-lag-behind-cUp until Visual Studio 2010, simple property definitions were always ridiculously verbose. For example ...http://graemehill.ca/visual-basic-10-properties-still-lag-behind-cFri, 02 Apr 2010 00:00:00 GMTLINQ to SQL Gotcha #6: Delete, Save, Insert, CRASHhttp://graemehill.ca/linq-to-sql-gotcha-6-delete-save-insert-crashIf you keep the same entity around after it has been deleted and SubmitChanges() is called then you can run into an InvalidOperationException if you try to insert it again ...http://graemehill.ca/linq-to-sql-gotcha-6-delete-save-insert-crashThu, 01 Apr 2010 00:00:00 GMTSingleton WCF service gotcha: allowing more than 10 connectionshttp://graemehill.ca/singleton-wcf-service-gotcha-allowing-more-than-10-connectionsBy default, an instance of a WCF service can only have 10 connections at a time. If your service is a singleton then there is obviously only one instance, which means that only 10 clients can connect to your service at a time. All subsequent connection attempts will result in timeouts if one of the 10 spots is not freed up. You can easily change this from the default by adding a serviceThrottling entry to your behavior definition in the app.config/web.config file. Here's an example that cranks the max up to 50 ...http://graemehill.ca/singleton-wcf-service-gotcha-allowing-more-than-10-connectionsThu, 01 Apr 2010 00:00:00 GMTUpdating and restarting a singleton WCF service hosted in IIShttp://graemehill.ca/updating-and-restarting-a-singleton-wcf-service-hosted-in-iisI recently moved a singleton WCF service to IIS that used to be hosted within a Windows service. When it was hosted in a Windows service restarting it was easy, you just go to the service manager in Windows and click restart, but to my knowledge there is no direct equivalent for a WCF service running inside IIS. Since a singleton service continues to run indefinitely once it starts I was afraid that even after publishing an update or changing the web.config the old code would continue to run until I forced a restart somehow. I didn't want to have to restart IIS every time there is a change to the config file, so I made a test project and ran some experiments. It turns out that when any change is made to the service (ie: any of the binaries, the svc file, or the web.config are replaced) the service immediately restarts. This means that all of your existing connections will be terminated and the service class will be recreated. Unlike a Windows service you don't have to manually force a restart when you publish an update. The bad news is that I still don't know of a way to simply restart the service without making any changes. Aside from restarting IIS (which is obviously a terrible solution) the only way I know is to make some random negligible change to the config file (like changing a comment or maybe even just whitespace). I guess that in theory singleton services are not meant to be restarted, but you're bound to want to do it at some point. http://graemehill.ca/updating-and-restarting-a-singleton-wcf-service-hosted-in-iisMon, 29 Mar 2010 00:00:00 GMTCruiseControl.NET: Versioning ccnet.config and integrating it into CIhttp://graemehill.ca/cruisecontrolnet-versioning-ccnetconfig-and-integrating-it-into-ciCruise Control is meant to help manage your builds based on the code in source control, and since ccnet config files are basically code, it only makes sense that they should be a part of this process. Basically, there are two problems I wanted to solve ...http://graemehill.ca/cruisecontrolnet-versioning-ccnetconfig-and-integrating-it-into-ciWed, 10 Mar 2010 00:00:00 GMTLINQ to SQL Gotcha #5: Column Default Valueshttp://graemehill.ca/linq-to-sql-gotcha-5-column-default-valuesA common pattern in database design is to use make a column required, give it a default value and then never think about it when doing INSERTs. A perfect example would be a createdDate column on the Users with a default value of GetDate(). Here's the full table definition ...http://graemehill.ca/linq-to-sql-gotcha-5-column-default-valuesSat, 06 Mar 2010 00:00:00 GMTLINQ to SQL Gotcha #4: ChangeConflictException on Update of Manually Attached Datahttp://graemehill.ca/linq-to-sql-gotcha-4-changeconflictexception-on-update-of-manually-attached-dataLINQ to SQL has built in optimistic concurrency checking. When you create an unattached entity and then attach it (ie: with the Attach() function) the concurrency check will always fail by throwing a ChangeConflictException unless one of the two are true ...http://graemehill.ca/linq-to-sql-gotcha-4-changeconflictexception-on-update-of-manually-attached-dataTue, 09 Feb 2010 00:00:00 GMTSaving changes to stored procedure results in LINQ to SQLhttp://graemehill.ca/saving-changes-to-stored-procedure-results-in-linq-to-sqlThe great thing about fetching data via a LINQ to SQL query is that you get a nice formatted result and you can easily save back any changes you make with SubmitChanges(). Unfortunately, we all inevitably fall into scenarios where we have to make use of stored procedures for performance or other reasons. If you have a stored procedure whose result set contains columns from just a single table then you can easily map the stored procedure to that table, but in most cases the result set involves multiple tables making things a little more tricky. It's easy to execute a stored procedure from LINQ to SQL (just drag the SP from the server explorer into the designer and then execute it like a function on the data context) but you lose some of the benefits of LINQ to SQL. First of all, you just get a flat result set instead of a hierarchical result set using the auto generated entity classes. Second, you can't just make changes to the result and call SubmitChanges. Luckily, with a little extra work, the flat, detached result set can be converted into a hierarchical, attached result set where changes can easily be saved ...http://graemehill.ca/saving-changes-to-stored-procedure-results-in-linq-to-sqlTue, 09 Feb 2010 00:00:00 GMTLINQ to SQL Gotcha #3: Chaining Where Clauseshttp://graemehill.ca/linq-to-sql-gotcha-3-chaining-where-clausesIn LINQ to SQL you can chain multiple where clauses like this ...http://graemehill.ca/linq-to-sql-gotcha-3-chaining-where-clausesFri, 05 Feb 2010 00:00:00 GMTWPF Responsiveness: Asynchronous Loading Animations During Renderinghttp://graemehill.ca/wpf-responsiveness-asynchronous-loading-animations-during-renderingDownload the code here: WpfLoadingOverlay.zip A common issue in MDI or TDI style user interfaces is that it can take a long time to render new forms when they are opened. Even a one or two second delay is enough to make an application seem very unresponsive. If there's nothing you can do to improve the actual performance (ie: the total time to load the form) you can at least improve the perceived performance. This code sample creates a simple form with a tab control and a button. Every time you click the button it adds a new tab with 4000 text boxes. Depending on the speed of your computer the form will probably take around five seconds to load. As soon as you click the button, the new tab appears with a loading animation that continues until the contents have been rendered. This is not a trivial task because we want to render a loading animation at the same time that we are waiting for another long rendering operation to complete. Basically, we need two rendering threads. You can't have multiple rendering threads in a single window, but you can put your loading animation in a new window with its own rendering thread and make it look like it's not a separate window. The loading overlay is a separate, chromeless window that does not appear on the taskbar and disappears as soon as loading is complete. The window is also semi-transparent and automatically positioned exactly over top of the form that is loading, so it looks like it is a part of the existing window. Download the sample project and try it out. http://graemehill.ca/wpf-responsiveness-asynchronous-loading-animations-during-renderingThu, 04 Feb 2010 00:00:00 GMTLINQ to SQL Gotcha #1: Unexpected LoadWith Behaviourhttp://graemehill.ca/linq-to-sql-gotcha-1-unexpected-loadwith-behaviourBy default, LINQ to SQL uses deferred loading. When you want to eager load an entity's associated data you need to set DataLoadOptions using the LoadOptions property on the DataContext. If you have a one-to-many relationship between Users and Articles you can force LINQ to SQL to eager load Articles with Users like this ...http://graemehill.ca/linq-to-sql-gotcha-1-unexpected-loadwith-behaviourSun, 31 Jan 2010 00:00:00 GMTLINQ to SQL Gotcha #2: GetChangeSet Weirdnesshttp://graemehill.ca/linq-to-sql-gotcha-2-getchangeset-weirdnessIf you attach an entity with a required association that is nulled out, you will be unable to call GetChangeSet(). In my opinion, the expected behaviour is that the entity should show up in the change set as though it is valid, but an exception should be thrown when you attempt to call SubmitChanges() because a foreign key constraint has been violated. In fact, with code like this we will get exactly that result (an exception is thrown on SubmitChanges()) ...http://graemehill.ca/linq-to-sql-gotcha-2-getchangeset-weirdnessSun, 31 Jan 2010 00:00:00 GMTSQL Server Management Studio and default databaseshttp://graemehill.ca/sql-server-management-studio-and-default-databasesThere is a really annoying bug (or at least what I would call a bug) in SQL Server Management Studio where you cannot login with a user whose default database does not exist. Even if you are already logged in and you rename the default database, you will automatically be logged out and will receive an error every time you try to login again. You can always login as a different user and change the default database, but if you only have access to the one account, you can change the default database using sqlcmd ...http://graemehill.ca/sql-server-management-studio-and-default-databasesSat, 30 Jan 2010 00:00:00 GMTHigh performance database rollback in automated tests with SQL Serverhttp://graemehill.ca/high-performance-database-rollback-in-automated-tests-with-sql-serverA couple months ago I wrote this article explaining why I think it is reasonable for unit tests to hit a real database. Subsequently, I wrote a follow up article describing some techniques for rolling back your database to its original state after each test. In that article I found that just using simple transactions did not solve the problem because you need access to all database connections being used, and they all have to be rolled back. I have since found a way around this problem using distributed transactions ...http://graemehill.ca/high-performance-database-rollback-in-automated-tests-with-sql-serverSat, 23 Jan 2010 00:00:00 GMTFinding all validation errors on an IDataErrorInfo objecthttp://graemehill.ca/finding-all-validation-errors-on-an-idataerrorinfo-objectWPF data binding has built in support for IDataErrorInfo, so it is easy to display a validation error when a property has invalid data. However, sometimes we need to manually find all the validation errors on an object. A perfect example of this is when trying to save data. Often you will want to verify that there are no validation errors before allowing the save operation to proceed. Using the MVVM pattern it would be ideal to determine whether there are any errors purely within your model view. The default behavior of IDataErrorInfo does not give a collection of all current errors. Instead, it will just tell you if a given property has an error (ie: using IDataErrorInfo.Item), so all we have to do to find all the errors is enumerate through each property on the class and call the Item property with that property name as the argument. The GetValidationErrors function below does exactly that ...http://graemehill.ca/finding-all-validation-errors-on-an-idataerrorinfo-objectTue, 27 Oct 2009 00:00:00 GMTSpecifying expected DataContext type in WPFhttp://graemehill.ca/specifying-expected-datacontext-type-in-wpfJosh Smith just made a blog post about XAML DataContext comments when using the MVVM pattern. He makes a great point, which is that in many cases it is not immediately obvious what the DataContext of a view is intended to be. A simple comment as Josh suggests will go a long way, but the downside is that comments create a maintainability issue. If you rename a model view, or refactor code so that a page, window or user control expects a different DataContext you also need to update the comment. Here's an example ...http://graemehill.ca/specifying-expected-datacontext-type-in-wpfSat, 24 Oct 2009 00:00:00 GMTConverting from SVN to Githttp://graemehill.ca/converting-from-svn-to-gitI held out for a while, but I have officially become a Git convert. Now that TortoiseGit has reached version 1.0 I can't think of a single way in which SVN is better that Git. There are a lot of advantages, but by far my favorite is the distinction between "commit" and "push". In any version control system it is good to commit as often as possible so that you have better version history, but in SVN every commit gets pushed to the server. This means that if you want to commit, but you are not ready to give the code to other developers (ie: the code does not belong on the trunk of the master copy) then you have to make a branch. In SVN it can be a major pain to do everything in banches because of poor (not to mention slow) merging functionality. With Git you can commit as many times as you want, then when your code is ready for the trunk, you can push it to the master server. Much more civilized! If you haven't tried Git yet then you should. You will be impressed. Here's an article on learning Git for SVN users: http://git.or.cz/course/svn.html http://graemehill.ca/converting-from-svn-to-gitSat, 17 Oct 2009 00:00:00 GMTMultiBindings are NOT useless in MVVMhttp://graemehill.ca/multibindings-are-not-useless-in-mvvmLately I have been detecting a growing sentiment that any use of MultiBinding is poor practice in MVVM (this thread on WPF disciples for example). However, I think people who say you should never use MultiBinding are missing its point. It is probably better to make a single binding to a FullName property than to multi bind to FirstName and LastName and then convert it into a full name. But there is still a scenario that demands the use of MultiBinding: bindings that need to update when more than one UI property changes. MultiBindings are not just used for passing more information to the converter, they also specify when the value needs to be updated and call the converter again. This is a much more important feature and it requires MultiBinding. http://graemehill.ca/multibindings-are-not-useless-in-mvvmSat, 17 Oct 2009 00:00:00 GMTUnit testing an Entity Framework DAL part 1: Just hit the databasehttp://graemehill.ca/unit-testing-an-entity-framework-data-access-layer-part-1-just-hit-the-databaseAs almost anyone who tries to unit test a database application will quickly discover, databases present a huge problem for unit testing. Strictly speaking, if you are testing your C# or VB code and you actually hit a real database, then it isn't really a unit test. It is actually an integration test. However, I have found that it doesn't really matter what you call it, the end result is that your tests are much more useful if they actually hit a real database. You don't have to worry about whether the test failed because you screwed up your mock object or if the actual application is buggy and you get better code coverage because even broken SQL will lead to a failed test ...http://graemehill.ca/unit-testing-an-entity-framework-data-access-layer-part-1-just-hit-the-databaseSat, 17 Oct 2009 00:00:00 GMTUnit testing an Entity Framework DAL part 2: Rolling back the test databasehttp://graemehill.ca/unit-testing-an-entity-framework-data-access-layer-part-2-rolling-back-the-test-databaseUpdate (Jan 23, 2010): I have made a new post explaining a method that I think is better than any of those described here. In part one I talked about how there is no true way to unit test your data access code under the standard definition of a unit test. However, I think it is useful to consider your database and your data access layer as a single unit when it comes to automated testing (read part one if you're wondering why). Everything is a trade off though so there are two important drawbacks to hitting a real database in your tests ...http://graemehill.ca/unit-testing-an-entity-framework-data-access-layer-part-2-rolling-back-the-test-databaseSat, 17 Oct 2009 00:00:00 GMTWPF super converters are bad for unit testinghttp://graemehill.ca/wpf-super-converters-are-bad-for-unit-testingI recently learned about a WPF converter library on CodePlex. They are all very flexible and it is pretty amazing what you can do with just a few converters. Here's a sample usage of one of the converters from the project's documentation ...http://graemehill.ca/wpf-super-converters-are-bad-for-unit-testingSat, 17 Oct 2009 00:00:00 GMTWPF nullable combo box source codehttp://graemehill.ca/wpf-nullable-combo-box-source-codeDownload the code here: WpfNullableComboBox.zip A few months ago I wrote this article on making a nullable combo box control in WPF. I had a bunch of requests to see an actual implementation, so here is a sample Visual Studio 2008 project with the source code for the user control. It basically uses the same technique I described in my previous blog post. All the combo box properties (even the obscure ones no one will ever use) are implemented. http://graemehill.ca/wpf-nullable-combo-box-source-codeWed, 26 Aug 2009 00:00:00 GMTEasier PropertyChanged notification with PostSharphttp://graemehill.ca/easier-propertychanged-notification-with-postsharpAs I described in this previous article raising the PropertyChanged event for classes that implement INotifyPropertyChanged can be a real pain. The biggest problem is that PropertyChangedEventArgs takes the name of the property that changed as a string and as we all know, strings are the root of all evil. Here I will show how to use a simple PostSharp attribute on your properties that need to raise the PropertyChanged event when they are changed so that you don't manually need to do it and hard code the name of the property as a string ...http://graemehill.ca/easier-propertychanged-notification-with-postsharpSat, 22 Aug 2009 00:00:00 GMTWPF rendering thread synchronizationhttp://graemehill.ca/wpf-rendering-thread-synchronizationDownload the sample project here: WpfRenderingThreadSynchronization.zip In most applications it is necessary to offload long running processes to an alternate thread so that the rest of the program does not lock up during that time. However, it's not so simple when the long running process is the actual rendering. Separate windows can have their own UI threads (as explained here) but to my knowledge there is no way to use multiple rendering threads on a single window ...http://graemehill.ca/wpf-rendering-thread-synchronizationSat, 22 Aug 2009 00:00:00 GMTSVN with Visual Studiohttp://graemehill.ca/svn-with-visual-studioHere are some tips for using SVN with a Visual Studio project ...http://graemehill.ca/svn-with-visual-studioTue, 19 May 2009 00:00:00 GMTDon't let "Option Strict Off" make you lazyhttp://graemehill.ca/dont-let-option-strict-off-make-you-lazyVB.NET has the sometimes useful feature of late binding, but this seems to lead to poor code. By default, late binding is enabled (ie: Option Strict is set to Off) allowing for implicit narrowing conversions (no cast). Although there are certainly cases where this is a useful feature that can cut down on the amount of reflection code left up to the programmer, I have found that it is more often a cause of less robust code and needless performance degradation ...http://graemehill.ca/dont-let-option-strict-off-make-you-lazyThu, 16 Apr 2009 00:00:00 GMTVerify your property names in INotifyPropertyChanged implementationhttp://graemehill.ca/verify-your-property-names-in-inotifypropertychanged-implementationUpdate: I have posted another article here that explains what I think is a better solution to this problem using a simple PostSharp attribute. When you raise the PropertyChanged event you have to pass it a property name as a string. If there is no property with that name then nothing will happen. The listener will not be notified and no exception will be thrown making the problem very difficult to debug. You can change this behaviour and make the application fail at runtime by adding a simple check to your helper function for the event ...http://graemehill.ca/verify-your-property-names-in-inotifypropertychanged-implementationSat, 28 Feb 2009 00:00:00 GMTNullable combo boxes in WPFhttp://graemehill.ca/nullable-combo-boxes-in-wpfUpdate: Sample source code demonstrating this technique can be downloaded here: WpfNullableComboBox.zip By default, combo boxes in WPF have some really annoying behaviour. When the control is initialized, if the SelectedItem is Nothing then the default selection will be blank, but as soon as you choose an item in the combo box, you can not reselect the blank/null option. One quick way around this is to add a null placeholder object to your ItemsSource. There are a few problems with this approach though ...http://graemehill.ca/nullable-combo-boxes-in-wpfFri, 20 Feb 2009 00:00:00 GMTBrutal loading times deleting files in Visual Studiohttp://graemehill.ca/brutal-loading-times-deleting-files-in-visual-studioI have long had an issue with Visual Studio where it takes a ridiculous amount of time to delete a file. Sometimes it takes over a minute and the IDE is completely unusable while it is loading. I finally came across a this post by Matt Hinze that gives a solution. Apparently when you delete a file it scans your recycle bin which can take a long time if there are lot of files in there. All you have to do is empty your recycle bin and you should be able to delete files with no noticeable delay. http://graemehill.ca/brutal-loading-times-deleting-files-in-visual-studioMon, 16 Feb 2009 00:00:00 GMTForcing form validation in WPF before user inputhttp://graemehill.ca/forcing-form-validation-in-wpf-before-user-inputBy default, validation is not enforced on a binding until after the value has been changed once. Consider this situation: A form has a text box whose contents should not be empty, but its starting value is the empty string. The text box will not show an error when the form is loaded. Instead, it will only show its error style after the user types in some text and then deletes it. Some people would call this a feature, but I prefer to have the validation checked right away so that I immediately know what the required fields are, and which starting values are invalid ...http://graemehill.ca/forcing-form-validation-in-wpf-before-user-inputThu, 12 Feb 2009 00:00:00 GMTManipulating automatically generated LINQ to SQL classeshttp://graemehill.ca/manipulating-automatically-generated-linq-to-sql-classesThere are a few problems with the data model code that is automatically generated in LINQ to SQL. The most obvious issues are that class names are not capitalized and that tables with two foreign keys to the same table will not have descriptive names. For example, if a table has columns firstUserID and secondUserID which are both foreign keys to the users table then you would probably hope to see the properties FirstUser and SecondUser on that class. Unfortunately, what you will actually get is User and User1 which is pretty much pointless because it is very difficult to tell which one is which. One way to tackle this is to simply change the code after it has been generated so that it looks like you want it to. But then as soon as you change the database and import the model again your changes are lost and have to be redone every time. Ideally, the automatically generated code would be formatted exactly as you want it ...http://graemehill.ca/manipulating-automatically-generated-linq-to-sql-classesWed, 11 Feb 2009 00:00:00 GMTDiscard changes in LINQ to SQL DataContexthttp://graemehill.ca/discard-changes-in-linq-to-sql-datacontextThe LINQ to SQL DataContext provides excellent functionality for managing a set of local changes to a database that can be pushed to the server with a single call to SubmitChanges(). Inevitably there will be situations where you want to discard the changes you have made, effectively allowing you to continue using the DataContext as though those changes had never been made. Unfortunately, there is no DataContext.DiscardChanges() method ...http://graemehill.ca/discard-changes-in-linq-to-sql-datacontextMon, 09 Feb 2009 00:00:00 GMT