Wednesday, October 22, 2008

Silverlight 2.0 on Silverlight Streaming

I spent this afternoon trying to post my beta of Catalyst Blockbuster (a tetris-like game developed in Silverlight 2.0). However, I was unable to get the Silverlight application hosted properly, and as such I removed the post for the time being.

It turns out the issues I was having were due to problems with Silverlight Streaming. I registered for an account and followed the directions to host a Silverlight application. However, whenever I tried to display my Silerlight 2.0 application through the iframe the service provides, I kept seeing the "Install Microsoft Silverlight" placeholder. After doing some extensive googling, I found the following thread on the Silverlight.net forums:

http://silverlight.net/forums/p/11060/115525.aspx#115525

It turns out that Silverlight Streaming does not currently support Silverlight 2.0 applications or streams. That thread does not contain information as to when the service will be updated. When it is updated, I will post the beta of Catalyst Blockbuster!

Friday, October 3, 2008

LINQ to SQL: Deleting Entities in Memory

In my previous post, I demonstrated how to use DeleteOnNull in LINQ to SQL database markup language (dmbl) association definitions in order to delete relational objects. However, DeleteOnNull is not the complete solution when working with relational objects in memory. The following example will better explain the situation where DeleteOnNull does not work.

In my database, I have an OrderDetail table that has a One-to-Many relationship with a Shipments table. Both of the business objects were generated using the Visual Studio 2008 dbml designer. In addition, I have the DeleteOnNull attribute for the association between the tables set to true.

Based upon the products in a given Order, my system will create appropriate Shipment objects. An example of constructing a shipment object and adding it directly to an OrderDetail is shown below:

1 OrderDetail od = new OrderDetail();

2

3 Shipment ship = new Shipment();

4

5 ship.Cost = 20.00M;

6 ship.Weight = 10.00M;

7 ship.TrackingNumber = "ABCD123456789";

8

9 od.Shipments.Add(ship);

In my application, the shipment objects are generated automatically depending on the products in the customer's shopping cart. Once the Shipment objects have been created, the user managing the order has the option to custom configure how many boxes and their weights should be shipped in order to reduce cost. The Shipment object is added directly to the OrderDetail's shipment collection.

The list of shipment objects were bound to a DataGridView with editing and deleting enabled. The DataSource of the DataGrid was set to od.Shipments.ToList(). However, I quickly discovered that despite the DeleteOnNull attribute being set to true for the association between OrderDetails and Shipments, attempting to delete a Shipment throws an InvalidOperationException with the following message:

"An attempt was made to remove a relationship between a OrderDetail and a Shipment. However, one of the relationship's foreign keys (Shipment.OrderDetailId) cannot be set to null."

After doing some research on the msdn forums, I discovered that the DeleteOnNull attribute does not work for items created in memory that are not attached directly to an Entity's source table. The ultimate solution in this case was to use the DataGridView's UserDeletingRow event with the following code:

1 private void shipmentDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)

2 {

3 Shipment temp = e.Row.DataBoundItem as Shipment;

4 _context.Shipments.Attach(temp);

5 _context.Shipments.DeleteOnSubmit(temp);

6 }


_context is the DataContext on which the Shipment object was originally created. By attaching the Shipment entity directly to the Shipments table and calling DeleteOnSubmit on the attached Shipment, the DataContext is able to successfully delete the Shipment object.

Wednesday, October 1, 2008

LINQ to SQL: DeleteOnNull

My first project at Catalyst just wrapped up this past week, and it involved creating an order fulfillment system using Microsoft .Net 3.5 WinForms technology.

For our data layer, we went ahead and used LINQ to SQL to interact with an installation of Microsoft SQL Server. Most of our business objects were generated via the designer for our DataContext.dbml file in Microsoft Visual Studio 2008. We decided to use LINQ to SQL with hopes of speeding up the development cycle. For the most part, LINQ to SQL fit our needs very well. However there were a few troublesome issues that I would like to see addressed in some form in future releases.

One of the issues I ran into several times while creating business object, was how to delete entities with associations in a relational database. When attempting to delete an entity that contains an association with another object in the database, by default the DataContext throws an InvalidOperationException, with a message similar to the following:

"An attempt was made to remove a relationship between a OrderDetail and a OrderLineItem. However, one of the relationship's foreign keys (OrderLineItem.OrderDetailId) cannot be set to null."

The relationship between an OrderDetail and OrderLineItem is one to many. By default, the DataContext attempts to set the OrderLineItem.OrderDetailId to null. However, we want the object to be removed from the database completely.

The solution to the issue is to set the Association's DeleteOnNull attribute to true. Unfortunately, this attribute cannot be set within the designer. Instead, the attribute must be added by hand within the DataContext.cs.designer file. An example if this implementation is below:


[Association(Name="OrderDetail_OrderLineItem", Storage="_OrderDetail", ThisKey="OrderDetailId", OtherKey="OrderDetailId", IsForeignKey=true, DeleteOnNull=true)]

Further explanations and examples of this issue can be found on Beth Massi's blog and Dinesh Kulkarni's blog.