Saturday, August 29, 2009

LINQ to SQL SubmitChanges Order of Operations

I did not realize the following is true in LINQ to SQL: Calling SubmitChanges fires ChangeSet changes in the following order:

  • Inserts
  • Updates
  • Deletes

Normally, this might not be a big deal, and you might never notice it, but it was the source of some pain on my current project.

Consider an order-entry screen that allows the user to add/edit/delete line items on an order.  The order-detail records are keyed by order-number/line-number, and this is the source of the problem.  If the user deletes line #1 in the order, what was originally line #2 gets re-ordered as line #1.  When the user decides they are done editing the order, they will then hit the save button and the queued up add/edit/delete operations are committed via the LINQ to SQL SubmitChanges command.

Fortunately, we were able to change the primary-key on our order-detail table, but we effectively lost some automatic data-integrity since we were previously able to ensure uniqueness on order-number/line-number.  For teams that don’t have the luxury of changing their database keys, this design decision by the LINQ to SQL team may be cause to move away from LINQ to SQL. 

Why the LINQ to SQL team decided to not submit changes in the order of operations, or allow the user to specify a non-default order to submit changes is beyond me.  I’m sure they had valid reasons for this decision, but it’s a bit short-sighted in that this interaction pattern is fairly common in order-entry system. 

This could perhaps been avoided by stamping various LINQ class members as virtual and letting us developers (consumers) override behaviors as we need – and assume the risks that come with overriding the framework code.

Tuesday, July 14, 2009

Linq to SQL Object Equality Issue

I started having some issues where Linq to SQL objects are "different” instances between calls to db.GetTable(type) and comparing objects returned.  In the majority of my types, object equality was working just fine, but in a few types, the hash-codes for otherwise “equal” objects was different, while the remainder of the object data was as expected.

Deleted the designer-objects and re-added to my DBML and the issue is resolved. 

A compare of my DBML file shows that the “IsPrimaryKey” attribute on my Identity columns was missing.  I had probably added the table to the DBML and realized later that I hadn’t specified a primary key and later added said key, without re-synchronizing my DBML.

Saturday, May 16, 2009

Mocking IQueryable

On my current project, we’ve been pretty successful in mocking out all of our LINQ to SQL repository operations, with one exception. One of our new methods returns an IQueryable object. No problem I think, I’ll just set an expectation on that call and return a list of the property entity type. But that gives me a build-error that I can’t convert a List<T> to IQueryable<T>.

A quick google yields the simplest of solutions to mocking IQueryable: the “AsQueryable” extension method. So now, my mock expectation returns something like “List<T>.AsQueryable” and all is well. This finding also clued me into a whole slew of interesting looking extension methods in the System.Linq namespace…..

Monday, April 06, 2009

LINQ to SQL and Overriding .Equals = not a good idea.

Short version: don’t override .Equals in your LINQ TO SQL entities, unless you really know what “equals” means to your objects!

Long version: on my current project, we’re using LINQ to SQL for our ORM needs, and it’s been working pretty well for us so far.  Pretty well, except for late last week when we realized that we weren’t properly persisting a number of records in our object graph.

We have a fairly complex object model, with some deep graphs of related objects, and have been using the .Add method to add child and grandchild objects into our “Order” object’s graph.  There was one particular “Child” record that was only being created one time per order, when we expected several variations of this child, yet only the first was being saved.

Our object graphs were build correctly, SubmitChanges was doing its job, we weren’t getting any errors, and yet these records just weren’t making it to the database.  After a few conversations with other people that have some LINQ to SQL experience and me trying some of the ugliest hacks I could think of, it dawned on me to try testing another theory I had – create another order-detail that looked similar to an existing order-detail.

Lo and behold, this similar order-detail also did not persist, and it was behaving like the other “exceptional” order-details – they were all in the object-graph, but not in the Insert Changes of my data-context!  Once I was able to see this, I took a closer look at the order-detail partial class we had written, and there I saw an overridden .Equals implementation.  Unfortunately, this .Equals was testing for property values within the order-detail to determine if a detail might match another detail instance, not testing for reference equality, which is evidently important to LINQ to SQL.

So there you have it – when working with LINQ to SQL entities, take care in how you decide to utilize the .Equals method and how you decide to override it.

Saturday, March 07, 2009

Managing Environment Specific Configurations Settings at Install Time

I’ve been asked a few times in the past few weeks about approaches for managing environment specific settings in config files.  Over the years, I’ve seen this solved a few different ways, and I tend to like the following approach:

  • Create a Setup project in your solution.
  • Open the User Interface Editor, and add a 3-button dialog to the setup (right-click the Start folder and choose “Add Dialog” and pick the 3-button dialog option)
  • Right-Click the newly added entry in the “Start” windows tree and select “Move Up”, so that this window is somewhere before the “Conform Install” dialog.
  • Edit the Properties Window for the 3-buttons window to be something like the following:

SetupProject3Buttons

  • In your main project (UI, Console, etc), add an XML file for the environment specific settings.  The schema should be something like the following:

<environments>
  <
environment name="Development">
    <
setting settingKeyPath="<your xpath here..>" propertyName="<your property here..>" propertyValue="<your value here…>" />
  </
environment>
…….repeat the environment section for each targeted environment

</environments>

  • In your main project, add a new class and have it implement the “Installer” class (found in System.Configuration.Install – so you’ll probably need to add a project reference to that assembly).
  • Override OnAfterInstall, but make sure you first call base.OnAfterInstall(), then start the process of applying your settings from the XML file created earlier to the config file of your installing application.
  • Your environment setting can be pulled from Context.Parameters[“ENVIRONMENT”]
  • Write yourself some code to read in the data in the XML file, and overwrite the appropriate settings in the config file.

That’s the basic steps I take to manage environment specific config file settings in my VisualStudio projects.

VS2008 Database Project Deployment Script Failures

On my current project, we’re using a database project to allow us to manage our schema changes. This has helped us keep all of our dev and build boxes in sync, and things are moving along smoothly.

However, there is one quirk that seems to burn me every few weeks. When we have a script failure, I scan through the output window to see where things went wrong. The IDE is even nice enough to let you click through to the failing line so you can figure out where things went wrong.

That’s nice and all, but the script that gets opened is the deployment script, not the actual .sql file that you created earlier. So, I end up making the change and rebuild/deploy only to get the same error, again. By now, when I review the output and realize what I did, I locate the actual post-deployment script file and make my edits there, rebuild/deploy and things work just fine.

How difficult would it have been to make the generated deployment script read-only so I wouldn’t keep getting burned by this quirk? Better yet, why not take me to the actual script file that caused the problem in the first place?

Thursday, February 19, 2009

Pandora WTF

I was sitting here jamming out to some Pandora this morning, and wondered what song I was hearing, so I flipped over to my desktop to see what was playing and I see this:

PandoraPanteraWTF

That’s the cover for Pantera’s Reinventing the Steel album??

Tuesday, February 10, 2009

Responsive WPF Interfaces

I had a bit of a challenge today while trying to get a WPF ProgressBar to send feedback to my UI while a long-running processes ran. 

My first challenge was finding “that one property that lets the ProgressBar animation run continuously” – IsIndeterminate

My next challenge was setting the IsIndeterminate property to true before firing off my long-running process.   I remembered something about using the Dispatcher, but even using that didn’t reflect the ProgressBar property changes to the UI.  I briefly considered trying an evil DoEvents type trick, but came to my senses before heading down that road.

I landed on creating a delegate which I could invoke to fire off my long-running process, and it ended up looking something like this (forgive the crude method names, this was some spike code I was playing around with:

private delegate void UpdateProgressbarIndeterminateState(bool isEnabled);
private void CompareClick(object sender, RoutedEventArgs e){
Dispatcher.Invoke(DispatcherPriority.Normal,
(UpdateProgressbarIndeterminateState)
delegate(bool isIndeterminate){
progressBar.IsIndeterminate = isIndeterminate;
}, true);

AsyncDelegate caller = PerformCompare;
caller.BeginInvoke(AfterCompareCallback, null);
}

internal delegate void AsyncDelegate();
private static void PerformCompare() {
DataComparer.Execute();
}

protected void AfterCompareCallback(IAsyncResult ar) {
Dispatcher.Invoke(DispatcherPriority.Normal,
(UpdateProgressbarIndeterminateState)
delegate(bool isIndeterminate) {
progressBar.IsIndeterminate = isIndeterminate;
}, false);
}

Tuesday, February 03, 2009

WPF DataGrid Conditional Formatting

I recently ran into a problem on my project where I needed to apply some conditional formatting to WPF DataGrid Cells based upon values from another property in my bound object.

The requirement was pretty simple: if condition is met, change the cell-text color to red, otherwise, leave it black.  What should have been a pretty simple task (never heard a programmer say that, right?) ended up taking me more time than I’d care to admit.

After fumbling around with a few attempts at the IValueConverter and a DataTemplateSelector, I still was not having any luck in getting my conditional formatting to work.  I eventually landed back at my usual source of information for the WPF ToolkitCodePlex, and “shockingly”, the answer was in the discussion for the project.

I had been fighting the “Foreground” property of the DataGridTextColumn directly, trying what was recommended in this article, but I just couldn’t get that working.  Once I followed the CodePlex forum recommendation of embedding a CellStyle into the DataGridTextColumn, things worked as expected.

Friday, January 30, 2009

Two-way Data Binding with WPF DataGrids

We’re making use of the the WPF Toolkit’s DataGrid control in my current project and have solved a few things along the way that weren’t entirely obvious to us at the start. One of these things was figuring out how to automatically reflect domain object changes in the UI.

Of the three developers on this project, Nik Clarkson has the most background with WPF and we usually throw out ideas to him and he “translates” what we want to do to into WPF terms and we’re off and running. In the case of getting our UI to reflect domain model changes, he mentioned BindingMode.

I was able to find some examples that showed how to do this in XAML pretty quickly, but I spent a few cycles trying to get this to work with a DataGridColumn that I was adding programmatically. My first attempt looked like how you’d do it in XAML a-la new Binding("Price, Mode = BindingMode.Two-way”), but that didn’t work.

I decided to make up a fresh batch of coffee in the team french-press, and then it hit me: object initializers. A quick edit and I ended up with following:

var priceColumn = new DataGridTextColumn{ Header = "Price", Width = DataGridLength.Auto,
Binding = new Binding("Price") { Mode = BindingMode.Two-way, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }};
ResultsGrid.Columns.Add(priceColumn);
This worked perfectly with the “Price” property I was binding to, since this was a property on one of our LINQ to SQL objects, and as such was raising the property-changed event for us in the generated code. When I went to do the same thing with another column (one not generated by the LINQ to SQL designer), I wasn’t seeing my edits reflected in my UI, but did see them in the domain objects via the debugger.

I had forgotten to raise the property-changed event in my ProposedPrice setter, so once I changed it to the following, everything worked great.
if (_proposedPrice != value)
{
SendPropertyChanging();
_proposedPrice = value;
SendPropertyChanged("ProposedPrice");
}

Wednesday, January 28, 2009

I just discovered something

One Kashi honey/cinnamon oatmeal packet plus a scoop of chocolate Muscle Milk with a bit of water and milk makes for one tasty breakfast/snack.

That is all.

Monday, January 26, 2009

Pasta Primavera

Here’s one of my old standby recipes that’s extremely easy to make and is quite tasty.

1lb cooked linguini 2 cups broccoli
2 tbsp olive oil 12oz fresh mushrooms
1 small zucchini cut in small sticks several cloves garlic – diced
1 small white onion 2 carrots cut into small sticks
1 small red bell pepper 12oz can evaporated skim milk
2 vegetable bullion cubes 1 1/4 tsp corn starch
2 plum tomatoes 2 tbsp parmesan cheese
Italian herbs (basil, oregano, etc)

In large skillet over medium heat, warm olive oil and then add mushrooms, onion, garlic and carrots. Stir frequently until almost tender then add red pepper and cook. In a separate pan, steam the broccoli for several minutes until tender and then set aside.

In blender, mix evaporated milk, vegetable bullion, corn starch and herbs (and a 1/2 tsp of salt if desired). Pour mixture over vegetables cooking in skillet and bring to boil. Cook for one minute, stirring nearly constantly.

After draining the pasta, return to a large pot (4 qt or so), dump the skillet contents over the pasta, and top with the tomato, broccoli and parmesan and stir.

Friday, January 16, 2009

AutoScroll panels in WPF

I’m still pretty new to WPF, coming from a WinForms background, and I keep running into situations where stuff that I can do easily in WinForms just isn’t there in WPF. Well, it’s there, I just don’t know how to do it. My latest example was a requirement to add some auto-scrolling to a WrapPanel, and I couldn’t find any sort of “overflow=auto” type setting on the WrapPanel, so off to Google I went.

Turns out WPF provides a pretty simple mechanism for allowing scroll: ScrollViewer. This control allowed me to do exactly what I needed to get done, but it needed to be treated as a container around my WrapPanel - a concept I’m seeing more and more as I get into WPF – another example of this was adding borders to a panel.

Here’s an example of a WrapPanel that has vertical auto-scrolling:

<ScrollViewer Name="MyScroller" VerticalScrollBarVisibility="Auto">
<WrapPanel Name="MyPanel"></WrapPanel>
</ScrollViewer>

LINQ to SQL Entity Association Quirks

On my current project, we’re trying to adhere to the Simplest Thing That Could Possibly Work principle and this unfortunately led to some pains with LINQ to SQL surfacing after we had claimed victory on a few stories.

We are early in this project, and didn’t have a wire-frame of what the screen flow would eventually look like, so we were just adding buttons to allow a user to see each piece of functionality as we delivered stories. But, as we finished each story, it became more and more clear that we needed to do some proper UI soon.

Enter “The Wizard”
We realized that the independent stories were really leading up to a flow of execution that a wizard style approach seemed to be a perfect fit for. Things came together pretty well, until I started to mess around with back-and-forward navigation and I started to get “An attempt was made to remove a relationship between a PARENT and a CHILD. However, one of the relationship’s foreign keys (CHILD.PARENT_ID) cannot be set to null”. This only occurred when I did any back-and-forward navigation and if I only navigated the happy-path straight through the wizard, things worked just fine.

Part of my problem was that I wasn’t submitting my changes until the user completed work in the wizard, but I was running code to disassociate existing entities (that may or may not have been persisted to the database) from local collections – each time the user left particular steps in the wizard. I was able to overcome some of those quirks with the “what didn’t work” approach below, but I still would saw the “null relationship” error on a fairly regular basis.

After much time searching Google, and trying a number of approaches as recommended here and here, I started to realize that I wasn’t properly disassociating my entities from their parent relationships before I deleted them.

What didn’t work:

try{
Repository.Delete(pricingElementDepartment);
}
catch(InvalidOperationException ) {}

What did work:

try{
childEntity.Parent = null;
Repository.Delete(childEntity);
}
catch(InvalidOperationException ) {}