Jim Rogers

Lives in Baton Rouge, LA, with two dogs, one cat, and one lovely wife. I'm a lead developer for GCR Incorporated.

Katrin and Jim

Month List

Generating .NET classes for XML deserialization

by jim Mar 15, 2013 2:15 PM

I'm not the world's biggest fan of XPATH queries, and they get tedious real fast if you need to search through sets of nodes in XML. It's much easier to deal with class objects. If you've got XML you want to deserialize, and need the class definition to do it, Microsoft has you covered:

  • Create a new XML file in Visual Studio, and paste your XML into it
  • On the XML menu chose "Create Schema"
  • Save the generated XSD file to a convenient location, like c:\temp\bing.xsd
  • Open a Visual Studio command prompt at this location - this is easier if you have the shell extension :-)
  • Run the xsd.exe tool to generate class files

C:\TEMP>xsd.exe c:\temp\bing.xsd /c /out:"c:\temp" /l:VB
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'c:\temp\bing.vb'.

C:\TEMP>

The generated code is far from ideal:

  • I don't need most of the properties
  • The class names are cumulative, and not intuitive, like ResponseResourceSetsResourceSetResourcesLocationGeocodePoint for the GeocodePoint element
  • Properties unnecessarily use a field backing store
  • Elements that appear once under the parent are assumed not to be collections - but I know in my case that some should be - i.e., they appear once just for this particular query, but may appear multiple times in others

But it's a good starting point for refactoring.

Tags: ,

Code

DbContext with linked servers

by Jim Aug 28, 2012 7:00 PM

Weird things happen when you try to use DbContext to update rows on a synonym which points to a linked server.

System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Unable to start a nested transaction for OLE DB provider "SQLNCLI10" for linked server "WebSQL". A nested transaction was required because the XACT_ABORT option was set to OFF.

If the changes can be rolled into a stored procedure, this is one solution; SET XACT_ABORT ON can be called at the beginning of the procedure. But this may not be simple, and kind of defeats the purpose of using Entity Framework.

Another solution is to set the XACT_ABORT option globally, for the server instance. This is a bit extreme. I actually found this little error when we turned that option OFF (the default) – it had been on, but that was breaking some Microsoft accounting software that lived on the server in question. So change this at the server level at your own risk…

I wrote a little class to set XACT_ABORT ON for my connection. It’s used like this:

Using New TransactAbortContext(MyDbContext)
    MyDbContext.SaveChanges()
End Using

And here’s the TransactAbortContext class:

Imports System.Data.Entity.Infrastructure
Imports System.Data.Entity

''' <summary> 
''' Put a "SET XACT_ABORT ON" command on the connection for a dbcontext 
''' </summary> 
''' <remarks> 
''' This is necessary when calling updates on a synonym which is actually
''' a reference to a linked table on another SQL Server instance. 
''' </remarks> 
Public Class TransactAbortContext
    Implements IDisposable

    Private _dbContext As DbContext
    Private _disposed As Boolean ' To detect redundant calls 

    Public Sub New(ByVal dbContext As DbContext)
        Dim objectContext = DirectCast(dbContext, IObjectContextAdapter).ObjectContext
        objectContext.Connection.Open()
        objectContext.ExecuteStoreCommand("SET XACT_ABORT ON")
        _dbContext = dbContext
    End Sub

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not _disposed Then
            If disposing Then
                Dim objectContext = DirectCast(_dbContext, IObjectContextAdapter).ObjectContext
                objectContext.Connection.Close()
            End If
        End If
        _disposed = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
End Class

A connection manually opened on the underlying ObjectContext is kept open and used for SaveChanges, until manually closed.

The TransactAbortContext class keeps track of this for the passed-in DbContext.

Checking for a ReCAPTCHA entry on the client

by Jim Feb 27, 2012 9:06 AM

ReCAPTCHA necessarily posts back to the server for validation of the entered text. However, if no text has been entered at all, then there's nothing to post back for. In ASP.NET web forms, we can use a CustomValidator control to check whether there's anything to submit, and if not, avoid the round trip to the server.

This example uses a ValidationSummary control (not shown.)

<asp:CustomValidator runat="server" ID="valCaptchaEntered" 
  ErrorMessage="Please complete the verification code (captcha)" 
  Display="None" ClientValidationFunction="validateCaptchaEntered">
</asp:CustomValidator> 
<div id="recaptcha_div"> 
<
recaptcha:RecaptchaControl ID="capLogin" runat="server"
PublicKey="[key]" PrivateKey="[key]"
Theme="white" CssClass="captcha" OverrideSecureMode="true" />
</
div>

Assuming you're using jQuery, the client side validation function is just a couple of lines, and looks like this:

// Make sure the user entered something into the captcha, so we don't round-trip to the 
// server if they've left it empty.
function validateCaptchaEntered(source, arguments) { var value = $.trim($("#recaptcha_response_field").val()); arguments.IsValid = (value != ""); }

Removing a #region with Resharper

by Jim Sep 22, 2011 8:28 PM

Collasped

I hate opening up a source file and seeing that. No, not the VB.NET, though I’m not a fan of that either. I mean the fifteen region directives in a 312 line file. Most of those have one method in them. I guess at some point that was a coding standard or something - but dude, you’re making the code harder to read, not easier.

Neither Visual Studio nor resharper has a direct means of quickly removing individual region directives, though resharper can be configured to remove all of them when you reformat the file.

To remove specific regions, follow these steps:

Type Ctrl+Alt+F to display resharper’s File Structure window, shown below. The gray outlines correspond to regions.

Click the ‘x’ in the upper right corner of the region box. The start and end region directives will be removed, but the code they contain will remain.

image

An obscure DB2 error

by Jim Aug 17, 2011 9:06 AM

SQL1159 Initialization error with DB2 .NET Data Provider, reason code 7, tokens 9.5.0.DEF.2, SOFTWARE\IBM\DB2\InstalledCopies

For me the solution to this error was simply this: run my .NET website under IIS, rather than under Visual Studio’s development server. There are apparently other sources of this error, maybe related to x86 vs. x64 installations; IBM has some documentation of the error types.

If I had to guess, I would think that the IBM driver DLLs are trying to read from the registry, and the development server doesn’t have the necessary permissions. Reason code 7 is a registry error, and the tokens are an existing registry value and path under HKEY_LOCAL_MACHINE.

Tags: ,

Code