This article describes the simplest way of how to do CRUD (Create, Retrieve, Update, Delete) operations in Silverlight using ADO.NET Data Service (Astoria). There are two ways to communicate with Database in Silverlight. 1) Web Service 2) ADO.NET Data Service. I chose ADO.NET Data Service for this article because RESTful Service and RIA (Rich Internet Application) development are the best match. If you have no idea about what ADO.NET is, please read my previous post here [1].
Download Sample: CRUDSilverlight.zip [2]
Contents
Note: If you already know about how to create the database in SQL 2005, please skip and jump to next section.
Step 1: Open SQL Server Management Studio Express

Step 2: Connect to SQL Server that you have installed on your local machine

Step 3: Right-click on Database node from Object Explorer and Select "New Database"

Step 4: Type your database name ( I named it "MyStore" in this sample) and Click "OK" button

Step 5: Right-click on Table node of the database that you have created and select "New Table"

Step 5: Create two columns called "ProductID(INT Identity PK)" and "ProductName". Name the table "Products"

Okay. That is all about creating new table in SQL 2005.
Note: I already explained about how to create ADO.NET Data Service in my previous article "Consuming ADO.NET Data Service (Astoria) from Silverlight [11]". (I will use ASP.NET 3.5 Extensions Web Application in this sample.) If you already read this post, please skip this section.
Step 1: Create new ASP.NET 3.5 Extensions Web Application

Step 2: Create “ADO.NET Entity Data Model”
After creating new ASP.NET 3.5 Ext project, you have to add "ADO.NET Entity Data Model" to your project. You have to generate the data model from the table that you have created in SQL 2005. If you want to see all screenshots for adding ADO.NET Entity Data Model, please check "Creating ADO.NET Entity Data Model" in this article [12].

Step 3: Create “ADO.NET Data Service”
After adding ADO.NET Entity Data Model, you have to add "ADO.NET Data Service" in your project. Then, you have to put the data source class name in first line and uncomment "config.SetResourceContainerAccessRule("MyEntityset", ResourceContainerRights.AllRead);" in InitializeService() function. Replace "MyEntityset" with "*" and change "AllRead" to "All".
public class WebDataService1 : WebDataService<MyStoreModel.MyStoreEntities>
{
// This method is called once during service initialization to allow
// service-specific policies to be set
public static void InitializeService(IWebDataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are
// visible, updatable, etc.
// (for testing purposes use "*" to indicate all entity sets/service
// operations, but that option should NOT be used in production systems)
// Example for entity sets (this example uses "AllRead" which allows reads but not writes)
config.SetResourceContainerAccessRule("*", ResourceContainerRights.All);
// Example for service operations
//config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
// Query interceptors, change interceptors and service operations go here
}
Step 4: Change the auto-assign port to specific port of your web application
Note that this step is very important. We should use the static port to prevent the cross-domain problem. Web tab is under the properties window of the project.

When I was writing how to consume ADO.NET Data Service in Silverlight [13], I didn't use Webdatagen.exe to generate the proxy class for Astoria. Bryant pointed me the way how to generate the proxy class in this post [14]. (Thanks a lot, Bryant) So, we can save our time for duplicating the class between Silverlight project and ASP.NET web project.
Products.cs is the name of proxy file that we want to generate. http://localhost:52799/WebDataService1.svc is the URL of ADO.NET Data Service.

Then, check the Products.cs under Microsoft ASP.NET 3.5 Extensions. You can add this proxy file to Silverlight project.
Okay. We have done the preparation to do CRUD operations in Silverlight using ADO.NET Data Service. Let's take a look how to do those operations.
You can create the instance of Products object and set the product name as you like. We don't need to specify the product id since the key is identity field. As we are adding the data, we will set the MergeOption to AppendOnly.
try{
MyStoreModel.Products _products = new MyStoreModel.Products();
_products.ProductName = "Windows Vista";
MyStoreModel.MyStoreEntities _mystore = new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;
_mystore.AddObject("Products", _products);
_mystore.SaveChanges();
insertTextBlock.Text = "New record has been added successfully. Please check Products table in SQL";
}
catch(Exception ex){
throw ex;
}
The code below is for updating the existing record in Database. We will use "OverwriteChanges" MergeOption for updateing.
try {
MyStoreModel.MyStoreEntities _mystore = new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
MyStoreModel.Products _products = new MyStoreModel.Products();
_products.ProductID = 1;
_products.ProductName = "Visual Studio 2008 Professional";
_mystore.AttachObject("Products", _products);
_mystore.UpdateObject(_products);
updateTextBlock.Text = "ProductID(#1) has been updated successfully. Please check Products table in SQL";
_mystore.SaveChanges();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
Note:
The ReadMe.txt of Astoria said ~
- Update (calling the UpdateObject followed by SaveChanges methods) may return an exception even though the operation succeeded on the server side.
So, you will get the exception while updating the record. but don't worry about that. Your record will be updated in SQL database even you got the exception. This is a known-issue that will be fixed in next release.
The following code is for retrieving the record from Database. You can also read other post "consuming the ADO.NET Data Service" in my blog.
try {
MyStoreModel.MyStoreEntities _mystore = new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
Microsoft.Data.WebClient.WebDataQuery<MyStoreModel.Products> products = _mystore.CreateQuery<MyStoreModel.Products>("/Products?$orderby=ProductID");
double top=0;
foreach (MyStoreModel.Products p in products) {
TextBlock tbk = new TextBlock();
tbk.Text = p.ProductName;
tbk.Height = 50;
top += tbk.Height;
tbk.SetValue(TopProperty, top);
view.Children.Add(tbk);
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}try {
MyStoreModel.MyStoreEntities _mystore = new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
MyStoreModel.Products _products = new MyStoreModel.Products();
_products.ProductID = 1;
_mystore.AttachObject("Products", _products);
_mystore.DeleteObject(_products);
_mystore.SaveChanges();
deleteTextBlock.Text = "ProductID(#1) has been deleted successfully. Please check Products table in SQL";
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
As there is no setting or web.config in Silverlight project, I chose to use the XML file to store the configuration information. But I think it might be better if we change the extension to config in real project. In this sample, I stored the Service URI in Configs.xml file.
<?xml version="1.0" encoding="utf-8" ?>
<ServiceUriString>http://localhost:52799/WebDataService1.svc</ServiceUriString>
As I don't want to load this XML by using WebRequest, I embedded this XML in project. The following code is for reading the XML file in Silverlight.
Stream stream = this.GetType().Assembly.GetManifestResourceStream("SilverlightProject1.Configs.xml");
XmlReader reader = XmlReader.Create(stream);
while (reader.Read()) {
if (reader.IsStartElement()) {
if ("ServiceUriString" == reader.LocalName) {
reader.Read();
string _serviceURL = reader.Value;
reader = null;
stream.Dispose();
return _serviceURL;
}
}
}
reader = null;
stream.Dispose();
return string.Empty;
That's all about doing CRUD operations in Silverlight. Sorry for not having the nice UI in my sample. As this article is focusing on CRUD operation, I don't want to add the complexities of UI code in the sample. I hope you will find it useful and feel free to let me know if you have any comment or suggest. Thanks.
Links:
[1] http://michaelsync.net/2008/01/29/adonet-data-service-in-plain-english
[2] http://michaelsync.net/demo/CRUDSilverlight.zip
[3] http://msdn2.microsoft.com/en-us/vstudio/products/aa700831.aspx
[4] http://msdn2.microsoft.com/en-us/express/bb410792.aspx
[5] http://www.microsoft.com/downloads/details.aspx?FamilyID=fd9c2a29-7383-4b2e-9ec9-0c6120718d4f&displaylang=en
[6] http://www.microsoft.com/downloads/details.aspx?FamilyId=A9C6BC06-B894-4B11-8300-35BD2F8FC908&displaylang=en
[7] http://www.microsoft.com/silverlight/license-win-dev.aspx?redirectid=Tue, 15 Jan 2008 17:02:52 GMT#4_13
[8] http://www.microsoft.com/downloads/details.aspx?familyid=15DB9989-1621-444D-9B18-D1A04A21B519&displaylang=en
[9] http://go.microsoft.com/fwlink/?LinkID=104985
[10] http://www.microsoft.com/downloads/details.aspx?familyid=D8AE4404-8E05-41FC-94C8-C73D9E238F82&displaylang=en
[11] http://michaelsync.net/2008/01/15/consuming-adonet-data-service-astoria-from-silverlight
[12] http://michaelsync.net/2008/01/15/consuming-adonet-data-service-astoria-from-silverlight
[13] http://michaelsync.net/2008/01/15/consuming-adonet-data-service-astoria-from-silverlight
[14] http://blogs.sqlxml.org/bryantlikes/archive/2008/01/28/consuming-astoria-from-silverlight.aspx
[15] http://michaelsync.net/2008/02/10/crud-operations-in-siverlight-using-adonet-data-service