Archive for September, 2007

CSLA : Step-by-Step , Relationships

Monday, September 24th, 2007

Due to popular demand…ok…just Phil … we’re back with the second installment of CSLA: Step-by-Step.

In the previous tutorial, we took a look at how to setup the various tools and templates to easily generate your first CSLA business object.
In this tutorial we’ll dive a little deeper into parent-child objects, and which CSLA object to use where.

The Relationship

For this example we’ll generate an Order object that has a collection of Order Details.
We’ll create the following classes:
  • Order (BusinessBase)
  • OrderDetail (BusinessBase)
  • OrderDetails (BusinessListBase)
Start by starting up CodeSmith and opening the EditableRoot.cst template. Fill in the property grid, to look like this:

 Order

Copy the generated code, create a new class in your NorthwindTraders project, called Orders, and paste the code. Next generate the stored procedures using MyGeneration.
You’ll notice that the compiler complains that OrderDetails are not defined on this line:

Private _orderdetails As OrderDetails = OrderDetails.NewOrderDetails()

We’ll get to that in a moment. Next, let’s generate the OrderDetail object. In CodeSmith open the EditableChild.cst template. Fill in the property grid to look like this:

 OrderDetail

Again, copy and paste the code in a class called OrderDetail.
You’ll notice the following comment in the AddInsertParameters sub:

‘todo: If parent use identity key, fix fk member with value from parent

Change this line:

cm.Parameters.AddWithValue("@OrderID", _orderID)

To this:

cm.Parameters.AddWithValue("@OrderID", parent.OrderID)

This is important so that the parent’s id is cascaded to the child object.

OK,so next we need to generate the OrderDetails class, that the compiler complained about. Using CodeSmith again open the EditableChildList.cst template and change the property grid to look like this:

 OrderDetails

Create the OrderDetails.vb class in your project and paste the generated code. The compiler should stop complaining about the OrderDetails object.

Allrighty. Now, we’ve got our Order Object and the Order Details collection(of Order Detail). We also have the stored procedures for the Order object, BUT just how will we get the Order Details? You’ll notice that in the Order Detail’s fetch method there is nothing about which stored proc to use. Not to worry.
You’ll notice that in the Order object’s ExecuteFetch method the FetchChildren sub is called. In this sub there is only 2 lines of code:

dr.NextResult()
_orderdetails = OrderDetails.GetOrderDetails(dr)

Now, in order for the datareader to actually read the NextResult we need to alter the Order object’s select stored procedure to also get the Order Details for the Order. Fire up your favourite query editor and change the Order’s select stored proc to look like this:

SELECT *
FROM [Orders] WITH (NOLOCK)
WHERE
[OrderID] = @OrderID

SELECT *
FROM [Order Details] WITH (NOLOCK)
WHERE
[OrderID] = @OrderID

This query will return 2 result sets, that’s the reason we need to use dr.NextResult. So with this one query you will automatically load the order and it’s child detail records. Cool huh?

Ok, so let’s recap. We’ve created a parent object named Order, a child object called OrderDetail and a collection of OrderDetail, called OrderDetails. We’ve changed the parent Order object’s stored procedure to also select the related child objects. And we’re ready to test our code.

Just as in part 1, let’s add the unit test code:

Namespace UnitTests

_
Public Class OrderUnitTests
Dim OrderID As Integer
Dim objOrder As Order

_
Protected Sub SetUpTest()
OrderID = 10248
objOrder = Order.GetOrder(OrderID)

End Sub

_

Public Sub FetchOrderChildren()
Assert.IsTrue(objOrder.Orderdetails.Count = 3, "Failed to get customer")
End Sub

End Class

End Namespace

You can test using TestDriven or the NUnit Gui. My test failed at first and I had to change this line in the OrderDetail class:


_discount = dr.GetDecimal("Discount")

To:


_discount = dr.Item("Discount")

And there you go! If your Order object return 3 Order Details, you know it’s working!

That concludes Part 2, I hope it was useful, please feel free to give your comments. In part 3, we’ll look at troubleshooting your objects and frequent errors as well as some more object integration.

Thanks for reading, I’ll chat to you soon.

ODBC Hell continued

Thursday, September 20th, 2007
Well, the migration of a client of mine’s MS Access system to SQL 2005, did not finish without any headaches. But finally it seems to be stable and the system is live.

One thing I’ve learned during this exercise is that MS Access has a tendency to teach bad habits. It’s an incredibly easy to use and powerful database platform, BUT, the fact that it does not enforce some basic database design rules is worrying.

For one, you can happily design tables without any primary keys. Now this works very nicely whilst the application is storing and retrieving it’s data from access, but as soon as you use the The Microsoft SQL Server Migration Assistant, to migrate the data to SQL and use the MS Access application as the front end, you start running into some interesting ODBC related data issues.

First and most important. When creating an ODBC data source for SQL 2005, use SQL Native Client, it’s the new ODBC interface for SQL server. You do get a few funnies when using the old SQL Server ODBC interface.

When linking an upgraded table(SQL server table) , without a primary key, Access will prompt you to select the field that uniquely identifies the table. This is a difficult task, considering you can’t really know without a primary key. One work around is to select up to 10 field that could possibly identify a record uniquely. This works, but is still risky, since there is no guarantee that the fields will always be unique per record.

Another issue I’ve discovered is that every query in MS Access that must return an editable recordset, must include the table’s primary key or unique fields. Thinking about all this it does make sense. The fact that MS Access allows users to get away with such design flaws in their databases is concerning.

I know of a few consultants/developers who cut their database development teeth with MS Access, myself included. In the last few months I’ve worked with a few "legacy" systems written in Access and it is obvious that the guys that wrote them, was learning as they go along, despite this fact they still billed the client a fairly large amount for their work. I have no problem with billing for your work, but…try to limit the amount of time billed for learning.

Error when adding new Data Source

Thursday, September 6th, 2007

I’ve experienced the strangest error when I try to add a new datasource via the Data Sources window in Visual Studio. The Data Source Configuration Wizards pops up, I select I want to bind to an object, click on next and get the following error:

DataSourceError
(Click to view larger image)

Yes, the dreaded Object reference not set to an instance of an object error.

After a considerable amount of time spent checking references, adding references, re-building and a lot of profanity, I finally discovered that VS expects a class in the root of your project for the Data Source Configuration Wizard to bind to an object. I moved all my forms and classes to folders within my project, thus I had no classes in the root of my project.

After creating an empty Class1.vb in the root of my project the error went away.

Go figure!!


Google Analytics integration offered by Wordpress Google Analytics Plugin