Thursday, December 23, 2004

Really obscure remoting error

I ran into the oddest error message today and thought I'd post the problem and solution up here. I was deploying our product on a test machine I have here at home which is a single processor P3 with Win2k3 Enterprise Edition loaded on it. The app's server piece runs under an ASP.NET remoting host and uses the binary formatter. No brainer really. Usually the typical error messages have to do with security, impersonation, database user, etc. Today I get this RETARDED message when running the client:

Exception Information
-------------------------------------------
Exception Type: System.ArgumentOutOfRangeException
Message: Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. Parameter name: ticks
ActualValue: NULL
ParamName: ticks
TargetSite: Void HandleReturnMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessage)
HelpLink: NULL
Source: mscorlib

StackTrace Information
-------------------------------------------

Server stack trace:
  at System.DateTime..ctor(Int64 ticks)
  at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadDateTime()
  at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadValue(InternalPrimitiveTypeE code)
  at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadMemberPrimitiveUnTyped()
  at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, IMethodCallMessage methodCallMessage)
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)
  at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryResponseMessage(Stream inputStream, IMethodCallMessage reqMsg, Boolean bStrictBinding)
  at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
  at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
  at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

Ummmm.... WTF!? Okay. Calm down. Ask Google what the problem is... it'll be okay. Well after asking Google groups I found a bunch of messages regarding the Process object... Definitely not related to anything I'm doing. I was just doing a simple remote method call... I wasn't even passing a DateTime value anywhere. This is bad. What do I do? I decided to try and delete the Temporary ASP.NET files so I look under the v1.1.4322 folder and guess what? I don't see the temp files' folder for my app! Hmmmmm.... So I have a look-see under the v2.0.40607 folder. There it is! Well that's not right!

It turns out the version of ASP.NET it was running under was incorrect. I opened up the virtual directory's property sheet and on the ASP.NET tab, sure enough, the version was set to 2.0. I switched it to 1.1 and everything worked like a charm. Looks like Win2k3 defaults to ASP.NET 2.0 when creating the virtual directory.

Update: The reason why my Win2k3 test server was defaulting to version 2.0 is because I have Whidbey loaded on that machine.

Sunday, December 19, 2004

It's nice to win

Raiders won today! And even though there's no playoff hopes at least Denver lost another one so I'm happy!

Friday, December 17, 2004

My thoughts on Datasets...

I know alot of people have been discussing the Dataset vs. O/R-Custom entity issue. I got involved in a similar topic on the Universal Thread today and thought I'd post my thoughts to this blog as well.

You should definately check out O/R tools and the object approach to creating entities, however, taking a data-based approach to your .NET applications is not a wrong way to go about things depending on your skill set and the type of application you are writing. In fact, you can end up with a very successful distributed entity-based application using datasets. If you prefer writing SQL-Statements to define your entities (views on your data), and are comfortable with having the complex rules and validations in separate objects then the entity-based approach using datasets may be the best choice for you. For instance, if you are familiar with building FoxPro applications this will probably be the easiest approach.

Using a pure O/R mapper means that you're taking a totally OOP approach and will create custom entities (instead of using the dataset as the entity). As many people point out there is a compelling reason to do so: You can encapsulate your business logic right into the entity. Also, it may be easier to exchange your entity with other non .NET systems. However, there are MANY compelling reasons to use datasets directly especially if you're sending them to Winforms clients:

1. Databinding is much easier with the Dataset. This is especially true for Winforms apps where you have 2-way data binding. If you create custom objects you will need to implement a handful of interfaces to get it to work: IBindingList, IList, IListSource, etc. I'm not saying you can't do it manually, but there's some work involved.

2. Filters/Sorting/Views are all made very very easy with the Dataset using the DataView.

3. Complex relationships between datatables can be easily created and managed and referential integrity can be enforced without having to go back to the database. Navigating from a parent row to the child rows in a related table is a snap.

4. AutoIncrementing columns automatically increment the keys when records are added.

5. Easy data manipulation and persistence. This is huge. The dataset takes care of remembering current and original values for you. It handles row state very well. If you add a record then delete it again inside the dataset there are no changes sent to the database. It persists relations, constraints, errors (row and column), calculated columns (expression-based), and has an extended properties collection in which you can put any additional information you need. The dataset also lends itself well to dynamic columns because on a Merge you can specify to automatically add any additional columns it finds. This is very powerful. Sure you can code all of this into your own entity object but you need to ask yourself is it worth it?

6. XML integration/serialization is a snap with ReadXML/WriteXML methods.

7. Simple data validation is built in. AllowNull, MaxLength, Referential integrity, uniqueness, data type. It also has an event model so that you can capture row/column changes. And with Row and Column errors (SetRowError/SetColumnError) you can easily indicate which rows/columns have problems and display them by databinding with the ErrorProvider. Complex validation or validator objects running on the middle-tier can simply set the row and/or column errors and send the dataset back to the client for resolution.

8. Strongly typed datasets are very easy to generate from an XSD file. That XSD which contains all of the schema information for the entity can be dynamically created by calling your middle-tier interfaces that return the Datasets (just temporarily set the DataAdapter's MissingSchemaAction setting to AddWithKey while you're generating them). Then you can run the xsd.exe utility to create the strongly-typed dataset code.

Keep in mind that datasets are NOT a business object in its traditional sense, they are simply the business data. Data is separated from behavior. If you think about data as being something that passes through your tiers and is validated, manipulated, twisted and banged into or by other objects (or other pieces of data) then choosing to use datasets is the right way to go. However, if you are more comfortable with the data as a real business object which encapsulates its own rules and behavior then use an O/R mapper and create custom business objects. But remember, if you are writing a complex Windows Forms business application then datasets "just work".

Of course, some O/R mappers work well with the entity-based approach too. I suggest you read this excellent post by Frans Bouma which may help you figure out what approach you should take.

Thursday, December 16, 2004

.NET Samples for Visual FoxPro Developers

For people of the Fox or anyone doing data-based applications in .NET check these out!

Catching up on .Net Rocks! radio show

I was catching up on episodes of DNR the other night and I have to say I really enjoyed episode #91 with Bily Hollis. Although I didn't agree with everything he said, I thought he was right on with his Windows forms architecure. It was nice to hear an expert has an architecture that uses the same concepts as the one I developed. I laughed out loud when he explained some of the real world things going on... and since I am developing Winforms applications and live in the real world it was refreshing to hear the practical side of things.

He has more of a VB background and I come from the FoxPro train of thought so it was cool to see that a VFP and a VB mind think alike when it comes to architecting business apps.

Wednesday, December 15, 2004

Props to all the Beta testers

I just wanted to say THANK YOU to all the dedicated beta testers out there. Especially Whidbey and Yukon. If it weren't for you guys the rest of us would be in a world of pain (instead you are! :-P). You guys are so cool. I teeter back and forth between loving and hating Betas. I love taking a look at new stuff so that I can plan for it in my current projects. But sometimes I just don't have the time to spend (waste?) on Beta testing. Rick points out some of the things I happen to agree with when testing Microsoft Betas these days.

I tend to focus on how to do things in the current versions of stuff because that's how the bills are paid. I admit I'm not as cool, but the stakeholders think I am. ;-)

Tuesday, December 14, 2004

Binary serialization of datasets

In version 1.1 of the .NET framework datasets can only serialize themselves as XML... even if you're using the BinaryFormatter. That can end up as a lot of extra crud on the wire. If you're sending datasets remotely to your clients you'll definately want to check this out. It's a surrogate class that gobbles up Datasets and converts all the dataset info into byte arrays and back again. As a test I had a dataset with 1000 records being sent across the internet and it took 12 seconds to load. Using the surrogate got me down to 3 seconds. Nice!

Enable/Disable databound controls automatically

Here's an easy way to automatically enable/disable databound controls when the CurrencyManager's position changes from/to -1:

Private Sub CmCustomer_PositionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles CmCustomer.PositionChanged
  If CmCustomer.Position = -1 Then
    Me.DisableDataControls(CmCustomer)
  Else
    Me.EnableDataControls(CmCustomer)
  End If
End Sub

Private _controlEnabledState As Hashtable

Private Sub EnableDataControls(ByVal cm As CurrencyManager)
  For Each b As Binding In cm.Bindings
    EnableControl(b.Control)
  Next
End Sub

Private Sub DisableDataControls(ByVal cm As CurrencyManager)
  For Each b As Binding In cm.Bindings
    DisableControl(b.Control)
  Next
End Sub

Private Sub DisableControl(ByVal c As Control)
  If (_controlEnabledState Is Nothing) Then
    _controlEnabledState = New Hashtable
  End If

  If Not (_controlEnabledState.Contains(c)) Then
    _controlEnabledState.Add(c, c.Enabled)
  End If

  If c.Enabled Then c.Enabled = False
End Sub

Private Sub EnableControl(ByVal c As Control)
  If Not (_controlEnabledState Is Nothing) Then
    If (_controlEnabledState.Contains(c)) Then
      If Not c.Enabled Then c.Enabled = DirectCast(_controlEnabledState(c), Boolean)
      _controlEnabledState.Remove(c)
    End If
  End If
End Sub
 

Monday, December 13, 2004

Monday Night

I didn't think the this would be that good of a game considering I don't really care about either team too much. Too bad KC won. Anyone watch Earthsea? How was it?

Racing wheels for sale

I've got some super light KMC-SR6 18 inch wheels for sale.

18" X 7.5"
5x100 bolt pattern
48mm offset

I know they'll fit Subaru and VW because they have the same bolt pattern. I paid $180/each and drove on them one day and decided I didn't like how they looked on my black WRX. I'm asking $400 +shipping.

SQL-Server schema query

Here's a SQL query I use everytime I need to regenerate my stored procedures or entities and I thought you may find it useful. The following statement is used to fill a dataset with two tables (two result sets are returned). Relate the two tables on table_name and set Nested=True on the relation. Then call WriteXml on the dataset to get an XML doc of your entire database schema. Use that in conjunction with your pretty little stylesheets and you can code generate anything that uses schema information from your database.

SELECT DISTINCT c.table_name
  FROM information_schema.columns c
  INNER JOIN information_schema.tables t ON c.table_name = t.table_name
  WHERE (t.table_type = 'BASE TABLE' and not (t.table_name = 'dtproperties'))
  ORDER BY c.table_name;
SELECT
  c.table_name,
  c.column_name,
  c.data_type,
  CASE c.is_nullable WHEN 'YES' THEN 1 ELSE 0 END AS is_nullable,
  c.column_default,
  c.character_maximum_length,
  c.numeric_precision,
  c.numeric_scale,
  c.datetime_precision,
  COALESCE ( (
    SELECT CASE cu.column_name WHEN null THEN 0 ELSE 1 END
      FROM information_schema.constraint_column_usage cu
      INNER join information_schema.table_constraints ct ON ct.constraint_name = cu.constraint_name
      WHERE ct.constraint_type = 'PRIMARY KEY' AND
            ct.table_name = c.table_name AND
            cu.column_name = c.column_name
  ),0) AS IsPrimaryKey
  FROM information_schema.columns c
  INNER JOIN information_schema.tables t ON c.table_name = t.table_name
  WHERE (t.table_type = 'BASE TABLE' AND NOT (t.table_name = 'dtproperties'))
  ORDER BY c.table_name, c.ordinal_position;

Anyone doing VBnet code generation...

.. may find this tool useful.

Sunday, December 12, 2004

I can't believe it..

The Niners won.

Okay that's more like it

I knew the Niners would mess up their 25 point lead... and they did it in less than 20 minutes.

The world must be ending...

.. the Niners are beating Arizona?

I wish VBnet had this

Dim someText As String

Text TO someText

Anything I type in here is placed into
the someText variable at runtime. No
more dealing with " & _

But that would be WAY too convenient.

End Text

(Yes, I ripped this off of VFP)

God, please make everyone use a friendlier web page format

Repeat after me: "Content on left, menu on right!" Let's not torture the smart phone user by making them scroll through the long list of links, archives and generally static menu items just so they can read your latest post!

There's always next year...

Damn Raiders! Curry out, Wheatly out and fact that they're so inconsistent is killing my fingernails... I think I bit off a cuticle. At least we beat Denver!