March 2009 - Posts
[This document supports a preliminary release of a software product
that may be changed substantially prior to final commercial release.
This document is provided for informational purposes only.]
SQL Data Services (SDS) is the relational database offering for the
Azure Services Platform. SDS exposes these relational capabilities
through the existing network protocol, Tabular Data Stream (TDS). TDS
is the underlying protocol used by all SQL Server client libraries such
as ADO.NET, ODBC and all other third party and open source access
libraries.
The use of the existing protocol enables the service to extend the
SQL data platform to the cloud while maintaining symmetry with the
existing SQL Server applications models.
SDS offers friction-free provisioning allowing customers to create
databases without having to worry about hardware and software
procurement, setup or maintenance. SDS also ensures high availability
and fault tolerance. The pay as you grow model provides unlimited scale
at low cost.
TDS access to the database services allows customer applications to
communicate with the service using existing client libraries (such as
ADO.NET, ODBC or JDBC).
Customers can optionally host their applications in Azure Compute as shown in the following illustration.
The exposure of the TDS protocol provides a programming model in the
cloud that is similar to the on-premise database programming
experience. Customers can easily migrate their applications from
on-premises databases into the cloud as the SQL surface area is largely
unchanged.
The database service exposes the strength of SQL Server, the power
of Transact-SQL and related richness of the existing SQL tools to
customers. Application developers can leverage their existing knowledge
when working with the service.
The Azure hosting services complement SDS allowing applications to
be hosted close to the database where the application data is stored
thereby reducing the overall cost of communicating with the service
while at the same time providing lower operational expenses.

High Level Architecture
As shown in the high level architecture diagram, TDS access to the
database services allows customer applications to communicate with the
service using existing client libraries (such as ADO.NET, ODBC or
JDBC). SQL Data Services provides:
- Provisioning service for on boarding new customers within the Azure platform.
- Billing,
metering and rollup functionality for users to discover service usage
information. This metrics information is also used for customer billing.
- Concepts
of Server and User Database which provides context for the management
of the databases in the cloud. SDS maps these logical concepts to the
underlying platform.

Migrating from ACE to the Relational Model
The
relational model described in this topic replaces the SDS ACE
(Authority, Container and Entity) model. The current SDS CTP
participants have the following options:
- Migrate existing applications to use the SDS relational
service. Customers can optionally host their applications in Azure
Compute.
- Use Windows Azure Storage for applications that don’t need relational capabilities
The SDS ACE model, with SOAP and REST interfaces, is being phased out.
I would like to share just a blog I saw regarding the changes Microsoft is implementing on SQL Data Services...
The no spin details on the new SDS features
Today we announced the details of our plans to accelerate the delivery of core relational database features as part of SDS. There
has been quite a bit of buzz about SDS over the past couple weeks and
it is great to be able to share the details more broadly.
If
we flash back about a year ago to Mix 08, Nigel Ellis got up on stage
to introduce the community to SDS which, at the time, was a flexible
entity based cloud database that you accessed using standard internet
protocols. We made this announcement with the promise that more
relational capabilities would be coming - and they did. But the
universal feedback we received from our TAP partners and other early
adopters was the need for a relational database delivered as a service.
This was extremely valuable feedback and drove us to more aggressively
investigate ways in which we could deliver these features. As a result
of that work and based on the progress we’ve since made in the product
team, we are announcing that SDS will deliver full relational database
capabilities as a service.
While
we knew we needed to accelerate our plans we also knew we needed to
hold true to some on the founding principles we had when we started our
journey. Things like High Availability, Fault Tolerance, Friction Free
Provisioning, Pay As You Grow Scaling, Immediate Consistency. We are
still delivering on these promises and have added to the mix true
relational capabilities, T-SQL and compatibility with the existing
developer and management tools ecosystem.
What
does this mean for developers? Developers will be able to very easily
provision themselves a logical server and database and begin developing
against it immediately using the existing tools and technologies that
they are accustomed to. We are providing an experience where a
developer can take an existing application and just change the
connection string to point it to the cloud and have it just work.
How
will we do it? Three letters TDS. TDS stands for Tabular Data Stream
and it's the published protocol that clients use to communicate with
SQL Server. From its inception, SDS has always been built on the SQL
Server technology foundation and it just made sense to allow our users
to access their data via TDS. Most importantly for developers, this
means symmetric SQL Server functionality and behavior combined with
compatibility with the existing tools you are familiar with.
Tables?...Check
Stored Procedures?...Check
Triggers?...Check
Views?...Check
Indexes?...Check
Visual Studio Compatibility?...Check
ADO.Net Compatibility?...Check
ODBC Compatibility?...Check
To be clear, the above is not a complete list of supported features. However,
given the feature set we are planning to support in SDS v1, a majority
of database applications will “just work”, allowing developers to
target on and off-premises deployments with essentially the same code
base. The initial scenarios we are targeting are
things like web and departmental applications. We will be posting some
content to our MSDN Dev Center in the coming weeks with specifics and getting started guidance but I encourage everyone to download SQL Express and the Windows Azure SDK to get started.
The
core foundational components of SDS have not changed. This is still the
same architecture that we have been telling you about for the past year
and that underlies the current CTP bits. It is the same architecture
that is powering some of Microsoft's key service properties and in the
next few months will be used to store 100’s of terabytes of data in
production deployments. Our early adopters (both internal and external)
have shaken it down pretty well and we feel very confident about these
bits. The only difference is we are now
providing a rich SQL model while maintaining the high availability,
fault tolerant and scale aspects of the system.
What
about the ACE (Authority, Container, Entity) data model and developer
experience? Since Windows Azure storage has a similar data model
(property bag) and developer experience, we will stop supporting the
current ACE Model sometime in the future. Does this mean you can't
access your relational data via internet friendly protocols like REST? Not
at all. You can still access your relational data (located on premises
or in the cloud) via HTTP/REST using the ADO.Net Data Services
framework. The compatibility with existing tools and technologies is a
really important point to drive home and a super important value add
that Microsoft provides.
Breadth
and OSS developer support will continue to be a high priority for us
and we will continue to support and provide breadth development
libraries for all mainstream development technologies including PHP,
Ruby and Java. If it works with SQL Server, it will largely work with SQL Data Services.
What
about Security? All communications with our service is SSL encrypted
and our initial authentication will be using SQL Authentication.
Of
course, SQL Data Services remains one of the key developer services of
the Azure Services Platform - that hasn't changed. Consuming SDS from
within an Azure application has never been easier and we will continue
to ensure this is a feature rich, friction-free experience.
I
have said a lot, so go ahead and digest all of this. What else do you
want to know? As I am sure you all have more questions, feel free to
email me at david.robinson@microsoft.com and I'll post the questions
and answers for all to see.
Kudos to SQL Data Services Team for the information on the blog. Refer to this link.
Console Application
The “Console Application 1” is the simple console program created to simulate the calls for each services. It has 5 .cs files. Additional project references: DataHelper, Model, TesterREST, TesterWCF and TesterWS.
Program.cs: this file is the main class for this program.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
namespace ConsoleApplication1
{
public class Program
{
static List<long> addUserWSTime;
static List<long> addUserWCFTime;
static List<long> addUserRestTime;
static List<long> getAllUsersWSTime;
static List<long> getAllUsersWCFTime;
static List<long> getAllUsersRestTime;
static List<long> updateUserWSTime;
static List<long> updateUserWCFTime;
static List<long> updateUserRestTime;
static List<long> deleteUserWSTime;
static List<long> deleteUserWCFTime;
static List<long> deleteUserRestTime;
static int tryID;
static int runNumber;
[STAThread]
static void Main(string[] args)
{
Stopwatch timerTotal = new Stopwatch();
Console.WriteLine("WS , REST and WCF Service Test will now start...");
Console.Write("Enter Try ID: ");
tryID = Convert.ToInt32(Console.ReadKey(false).KeyChar.ToString());
Console.WriteLine();
Console.Write("Enter Number of Run: ");
runNumber = Convert.ToInt32(Console.ReadLine().Trim());
Console.WriteLine();
Console.WriteLine("Press any key to start...");
Console.ReadKey(true);
timerTotal.Start();
addUserRestTime = new List<long>();
addUserWCFTime = new List<long>();
addUserWSTime = new List<long>();
getAllUsersRestTime = new List<long>();
getAllUsersWCFTime = new List<long>();
getAllUsersWSTime = new List<long>();
updateUserRestTime = new List<long>();
updateUserWCFTime = new List<long>();
updateUserWSTime = new List<long>();
deleteUserRestTime = new List<long>();
deleteUserWCFTime = new List<long>();
deleteUserWSTime = new List<long>();
UserProfileBL _objProfileBL;
int maxRunNumber = runNumber;
string constFName="Auto Test FN ";
string constLName="Auto Test LN ";
for (int ctr = 1; ctr <= maxRunNumber; ctr++)
{
_objProfileBL = new UserProfileBL();
string fName = string.Format("{0}{1}",constFName, ctr.ToString("000000"));
string lName = string.Format("{0}{1}",constLName, ctr.ToString("000000"));
TestAddUser(new Guid(), fName, lName);
TestGetAllUsers();
TestUpdateUser(_objProfileBL.GetGuids(fName), fName, lName);
_objProfileBL = null;
}
for (int ctr = 1; ctr <= maxRunNumber; ctr++)
{
_objProfileBL = new UserProfileBL();
string fName = string.Format("{0}{1}", constFName, ctr.ToString("000000"));
string lName = string.Format("{0}{1}", constLName, ctr.ToString("000000"));
Console.WriteLine(string.Format("Deleting : {0}", fName.ToString()));
TestDeleteUser(_objProfileBL.GetGuids(fName));
_objProfileBL = null;
}
timerTotal.Stop();
Console.WriteLine(string.Format("Total Execution Time for Tests: {0} m {1} s {2} ms", timerTotal.Elapsed.Minutes, timerTotal.Elapsed.Seconds, timerTotal.Elapsed.Milliseconds));
timerTotal = new Stopwatch();
timerTotal.Start();
GenerateReports();
timerTotal.Stop();
Console.WriteLine(string.Format("Total Report Creation Time: {0} m {1} s {2} ms", timerTotal.Elapsed.Minutes, timerTotal.Elapsed.Seconds, timerTotal.Elapsed.Milliseconds));
Console.WriteLine("Tests Finished...");
Console.WriteLine(string.Format("Report Saved at {0}", "TestReports Table!"));
Console.ReadKey();
}
static void GenerateReports()
{
ReportBL objBLReport = new ReportBL();
//WS
int runCtr=1;
foreach (long l in addUserWSTime)
{
objBLReport.AddReport(runCtr, "WS", "AddUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in getAllUsersWSTime)
{
objBLReport.AddReport(runCtr, "WS", "GetAllUsers", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in updateUserWSTime)
{
objBLReport.AddReport(runCtr, "WS", "UpdateUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in deleteUserWSTime)
{
objBLReport.AddReport(runCtr, "WS", "DeleteUser", l, tryID);
runCtr++;
}
//WCF
runCtr = 1;
foreach (long l in addUserWCFTime)
{
objBLReport.AddReport(runCtr, "WCF", "AddUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in getAllUsersWCFTime)
{
objBLReport.AddReport(runCtr, "WCF", "GetAllUsers", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in updateUserWCFTime)
{
objBLReport.AddReport(runCtr, "WCF", "UpdateUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in deleteUserWCFTime)
{
objBLReport.AddReport(runCtr, "WCF", "DeleteUser", l, tryID);
runCtr++;
}
//REST
runCtr = 1;
foreach (long l in addUserRestTime)
{
objBLReport.AddReport(runCtr, "REST", "AddUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in getAllUsersRestTime)
{
objBLReport.AddReport(runCtr, "REST", "GetAllUsers", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in updateUserRestTime)
{
objBLReport.AddReport(runCtr, "REST", "UpdateUser", l, tryID);
runCtr++;
}
runCtr = 1;
foreach (long l in deleteUserRestTime)
{
objBLReport.AddReport(runCtr, "REST", "DeleteUser", l, tryID);
runCtr++;
}
}
static void TestAddUser(Guid _id,string _firstname,string _lastname)
{
Guid Id = _id;
string FirstName = _firstname;
string LastName = _lastname;
Stopwatch timer;
Console.WriteLine("Processing AddUser...");
//WS
timer = new Stopwatch();
timer.Start();
TesterWS.TesterWS objTesterWS = new TesterWS.TesterWS();
TesterWS.UserInfo infoWS = new TesterWS.UserInfo();
infoWS.FirstName = FirstName;
infoWS.LastName = LastName;
infoWS.ID = Id;
objTesterWS.AddNewUser(infoWS);
timer.Stop();
addUserWSTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WS Finished...");
//REST
timer = new Stopwatch();
timer.Start();
TesterREST.TesterRest objTesterRest = new TesterREST.TesterRest();
Model.UserInfo infoRest = new Model.UserInfo();
infoRest.FirstName = FirstName;
infoRest.LastName = LastName;
infoRest.ID = Id;
objTesterRest.AddNewUser(infoRest);
timer.Stop();
addUserRestTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("REST Finished...");
//WCF
timer = new Stopwatch();
timer.Start();
TesterWCF.TesterWCF objTesterWCF = new TesterWCF.TesterWCF();
Modelo.UserInfo infoWCF = new Modelo.UserInfo();
infoWCF.FirstName = FirstName;
infoWCF.LastName = LastName;
infoWCF.ID = Id;
objTesterWCF.AddUser(infoWCF);
timer.Stop();
addUserWCFTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WCF Finished...");
}
static void TestGetUser()
{
}
static void TestGetAllUsers()
{
Stopwatch timer;
Console.WriteLine("Processing GetAllUsers...");
//WS
timer = new Stopwatch();
timer.Start();
TesterWS.TesterWS objTesterWS = new TesterWS.TesterWS();
objTesterWS.GetAllUsers();
timer.Stop();
getAllUsersWSTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WS Finished...");
//REST
timer = new Stopwatch();
timer.Start();
TesterREST.TesterRest objTesterRest = new TesterREST.TesterRest();
objTesterRest.GetAllUsers();
timer.Stop();
getAllUsersRestTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("REST Finished...");
//WCF
timer = new Stopwatch();
timer.Start();
TesterWCF.TesterWCF objTesterWCF = new TesterWCF.TesterWCF();
objTesterWCF.GetAllUsers();
timer.Stop();
getAllUsersWCFTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WCF Finished...");
}
static void TestUpdateUser(Guid[] _ids,string _firstname,string _lastname)
{
Guid[] Ids = _ids;
string FirstName = _firstname + " Updated";
string LastName = _lastname + " Updated";
Stopwatch timer;
Console.WriteLine("Processing UpdateUser...");
//WS
timer = new Stopwatch();
timer.Start();
TesterWS.TesterWS objTesterWS = new TesterWS.TesterWS();
TesterWS.UserInfo infoWS = new TesterWS.UserInfo();
infoWS.FirstName = FirstName;
infoWS.LastName = LastName;
infoWS.ID = Ids[0];
objTesterWS.UpdateUser(infoWS);
timer.Stop();
updateUserWSTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WS Finished...");
//REST
timer = new Stopwatch();
timer.Start();
TesterREST.TesterRest objTesterRest = new TesterREST.TesterRest();
Model.UserInfo infoRest = new Model.UserInfo();
infoRest.FirstName = FirstName;
infoRest.LastName = LastName;
infoRest.ID = Ids[1];
objTesterRest.UpdateUser(infoRest);
timer.Stop();
updateUserRestTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("REST Finished...");
//WCF
timer = new Stopwatch();
timer.Start();
TesterWCF.TesterWCF objTesterWCF = new TesterWCF.TesterWCF();
Modelo.UserInfo infoWCF = new Modelo.UserInfo();
infoWCF.FirstName = FirstName;
infoWCF.LastName = LastName;
infoWCF.ID = Ids[2];
objTesterWCF.UpdateUser(infoWCF);
timer.Stop();
updateUserWCFTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WCF Finished...");
}
static void TestDeleteUser(Guid[] _ids)
{
Guid[] Ids = _ids;
Stopwatch timer;
Console.WriteLine("Processing DeleteUser...");
//WS
timer = new Stopwatch();
timer.Start();
TesterWS.TesterWS objTesterWS = new TesterWS.TesterWS();
objTesterWS.DeleteUser(Ids[0]);
timer.Stop();
deleteUserWSTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WS Finished...");
//REST
timer = new Stopwatch();
timer.Start();
TesterREST.TesterRest objTesterRest = new TesterREST.TesterRest();
objTesterRest.DeleteUser(Ids[1]);
timer.Stop();
deleteUserRestTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("REST Finished...");
//WCF
timer = new Stopwatch();
timer.Start();
TesterWCF.TesterWCF objTesterWCF = new TesterWCF.TesterWCF();
objTesterWCF.DeleteUser(Ids[2]);
timer.Stop();
deleteUserWCFTime.Add(timer.ElapsedMilliseconds);
Console.WriteLine("WCF Finished...");
}
}
}
ReportBL.cs: this is the BusinessLayer that will call the DataLayer of the reporting in order to perform the operation in the Database.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class ReportBL
{
ReportDataAccess _data = new ReportDataAccess();
public ReportBL()
{
}
public void AddReport(int runId, string serviceType, string methodName,
long elapsedTime, int tryId)
{
_data.AddReport(runId, serviceType, methodName, elapsedTime, tryId);
}
}
}
ReportDataAccess.cs: this is the DataLayer of the Reporting.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using DataHelper;
namespace ConsoleApplication1
{
public class ReportDataAccess:DataAccessBase
{
public ReportDataAccess()
{
}
public void AddReport(int runId, string serviceType, string methodName,
long elapsedTime, int tryId)
{
DbParameterCollection parameters = new DbParameterCollection();
SqlParameter pRunId = new SqlParameter("@RunId", SqlDbType.Int);
pRunId.Value = runId;
parameters.Add(pRunId);
SqlParameter pServiceType = new SqlParameter("@ServiceType", SqlDbType.VarChar, 5);
pServiceType.Value = serviceType;
parameters.Add(pServiceType);
SqlParameter pMethodName = new SqlParameter("@MethodName", SqlDbType.VarChar, 20);
pMethodName.Value = methodName;
parameters.Add(pMethodName);
SqlParameter pElapsedTime = new SqlParameter("@ElapsedTime", SqlDbType.Int);
pElapsedTime.Value = elapsedTime;
parameters.Add(pElapsedTime);
SqlParameter pTryId = new SqlParameter("@TryId", SqlDbType.Int);
pTryId.Value = tryId;
parameters.Add(pTryId);
this.ExecuteNonQuery(
"INSERT INTO TestReports (RunId,ServiceType,MethodName,ElapsedTime,TryId) " +
"VALUES (@RunId,@ServiceType,@MethodName,@ElapsedTime,@TryId)", parameters);
}
}
}
UserProfileBL.cs: this is the BusinessLayer that will call the DataLayer of the UserProfile in order to fetch the IDs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class UserProfileBL
{
public UserProfileBL()
{
}
public Guid[] GetGuids(string filterName)
{
UserProfileData _data = new UserProfileData();
return _data.GetAll(filterName);
}
}
}
UserProfileDataAccess.cs: this is the DataLayer of the UserProfile that will fetch the IDs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using DataHelper;
namespace ConsoleApplication1
{
public class UserProfileData : DataAccessBase
{
public UserProfileData()
{
}
public Guid[] GetAll(string filtername)
{
List<Guid> _guids = new List<Guid>();
DataTable dt = this.ExecuteDataTable("SELECT ID FROM UserProfile WHERE FirstName LIKE '%" + filtername + "%'");
foreach (DataRow row in dt.Rows)
{
_guids.Add(new Guid(row["ID"].ToString()));
}
return _guids.ToArray();
}
}
}
RESPONSE TIME AND BANDWIDTH USAGE OF THE SERVICE
The simple Console Application was created in order to simulate the calls for each service and record the Response Time for each method and call. The result was stored in the Database with the following information: “Method Name” (The name of the method used e.g AddUser, DeleteUser), “Service Type” (The type of service e.g WS, REST, WCF), “Elapsed Time” (Response Time of the call), “RunID” (The Id of the thread), “TryID” (The Id of the trial made).
In order to avoid (or lessen) the SQL data cache, the method were executed (or called) as: AddUser first, followed by UpdateUser that was added, then GetAllUsers and finally, DeleteUser. The table was pre-populated with 13 records in which it won’t be modified / removed.
The Fiddler2 was used to capture the number of calls, bytes sent and received though out the processing of the method in the service.
The services were called as: WS, followed by REST and finally WCF.
During our attempts and trials during the test we did, it seems that among the differenct services, the WCF Rest and the Web Service SOAP utilizes the most efficient approach since it is only consuming very minimal bandwidth. The WCF-WCF communication to our surprise seems to be less efficient since it is consuming to much bandwidth due to the multiple requests it sends to the server. During our quality testing, the WCF Rest and the Web Service SOAP takes the lead on our study.
Upon executing the Console Application made to simulate the call of each service, and from a lot of trials made to the calls (Figure 1), it turns out that REST has the lowest Response Time, followed by the WS. Whereas, the WCF has the highest Response Time among the different services.
From the information retrieved in the Fiddler2, and tallying the results, it was a shocking result produced. The REST and WS are both have only 1 call needed to complete the process (single method e.g. AddUser, DeleteUser), whereas the WCF needed 5 calls just to complete the process. By summing up the bytes and number of calls made (Figure 2), the REST has the lowest number of bytes sent and received, followed by WS which is more than 50% higher bytes sent and received compared to REST, and lastly WCF which is almost 300% higher bytes sent and received compared to REST.
Figure 1: Response Time

Figure 2: Bandwidth Usage

Considering the idea that we might utilize the services on a cloud computing environment, we must take into consideration the total amount of bytes sent and received on our services since cloud computing costs is based on the bytes used rather than the amount of requests sent and received. But since limiting the number of requests would also take a weight on the response and the bandwidth consumption it is better that we limit it.
Assuming we will use Amazon Cloud Computing (Since Windows Azure as of the moment does not release and actual cost of the service), based on the results above on the bandwidth usage, here are the financial forecasted results.
Figure 3. Forecast
|
|
WCF REST
|
WS SOAP
|
WCF - WCF
|
|
Session Length (in minutes)
|
30
|
30
|
30
|
|
No. Of Sessions (No. Of Users)
|
1000
|
1000
|
1000
|
|
No. Of Transactions / session
|
4
|
4
|
4
|
|
Cost per hour (Instance Cost)
|
$ 0.30
|
$ 0.30
|
$
0.30
|
|
Transactions Cost / GB (Sent)
|
$
0.17
|
$ 0.17
|
$
0.17
|
|
Transactions Cost / GB (Received)
|
$
0.10
|
$ 0.10
|
$
0.10
|
|
Total Bytes Sent in Bytes (Per
Session)
|
857
|
3123
|
80068
|
|
Total Bytes Received in Bytes (Per
Session)
|
7766
|
9023
|
87387
|
|
Subtotal for the Session
|
$ 0.30
|
$ 0.30
|
$ 0.30
|
|
Subtotal for Trans Cost (Sent) / hr
|
$ 0.000145690000
|
$ 0.000530910000
|
$ 0.013611560000
|
|
Subtotal for Trans Cost (Receive)
/hr
|
$ 0.000003106400
|
$
0.000003609200
|
$ 0.000034954800
|
|
Total / Hr
|
$ 0.3001487964
|
$
0.3005345192
|
$ 0.3136465148
|
|
Total / Day
|
$ 7.2035711136
|
$
7.2128284608
|
$
7.5275163552
|
|
Total / Month
|
$
216.1071334080
|
$
216.3848538240
|
$ 225.8254906560
|
|
Total / Year
|
$
2,593.2856008960
|
$
2,596.6182458880
|
$
2,709.9058878720
|
As what you can see on figure 3, WCF Rest basically is the cost effective solution in terms of the amount of bytes sent and received by the system. The Web Services SOAP is also a viable solution for us however; this is based on the computation on available pricing as of the moment. If Microsoft releases its official offering, we might have to reconsider the technology based on pricing. On this part, WCF Rest again takes the lead over the 3 services.
CONCLUSION
After the study made on the services, it turns out that our expectation is wrong. The study clearly showed us that REST has the faster processing time shown in the Response Time and consuming the lowest bandwidth thru the use of bytes sent and received. WCF has the slowest Response Time and highest bandwidth usage. And lastly, WS which is in the middle of the two that has a medium Response Time and medium bandwidth usage.
Continuing on the article, here are the codes used for the different Communication methods.
Services
WCF-WCF
The WCF-WCF Service has 2 Files, the “UserAddress.cs” inheriting from “IUserAddress.cs” (an interface). Additional Project References are: BL and Model.
UserAddress.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Xml.Linq;
namespace SampleWCFLibrary
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,
ConcurrencyMode=ConcurrencyMode.Multiple
,MaxItemsInObjectGraph=1000000)]
public class UserAddress : IUserAddress
{
public void AddUser(Model.UserInfo user)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Add(user);
}
public Model.UserInfo GetUser(Guid id)
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.Get(id);
}
public List<Model.UserInfo> GetAllUsers()
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.GetAll();
}
public void DeleteUser(Guid id)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Delete(id);
}
public void UpdateUser(Model.UserInfo user)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Update(user);
}
}
}
IUserAddress.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
[assembly: ContractNamespace("", ClrNamespace = "SampleWCFLibrary")]
namespace SampleWCFLibrary
{
[ServiceContract]
public interface IUserAddress
{
[OperationContract]
void AddUser(Model.UserInfo user);
[OperationContract]
Model.UserInfo GetUser(Guid id);
[OperationContract]
List<Model.UserInfo> GetAllUsers();
[OperationContract]
void DeleteUser(Guid id);
[OperationContract]
void UpdateUser(Model.UserInfo user);
}
}
REST
The REST service has 1 item called “WCF Service”. Additional project references: BL and Model. The markup of the service (right-click the .svc file and choose view markup) should contain this code:
<%@ ServiceHost Language="C#" Debug="true" Service="MyRestTest.Service" CodeBehind="MyService.svc.cs" Factory="MyRestTest.AppServiceHostFactory" %>
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Microsoft.ServiceModel.Web;
namespace MyRestTest
{
class AppServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new WebServiceHost2(serviceType, true, baseAddresses);
}
}
}
The .svc.cs file should contain the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
using Microsoft.ServiceModel.Web;
[assembly: ContractNamespace("", ClrNamespace = "MyRestTest")]
namespace MyRestTest
{
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract]
public class Service
{
[WebGet(UriTemplate = "/adduser?user={user}")]
[OperationContract]
public void AddUser(string user)
{
XElement elem = XElement.Parse(user);
Model.UserInfo userInfo = new Model.UserInfo();
foreach (XElement e in elem.Elements())
{
switch (e.Name.LocalName)
{
case "FirstName": userInfo.FirstName = e.Value; break;
case "LastName": userInfo.LastName = e.Value; break;
case "ID": userInfo.ID = new Guid(e.Value); break;
}
}
BL.UserBL _objBL = new BL.UserBL();
_objBL.Add(userInfo);
}
[WebInvoke(UriTemplate = "/getuser?id={id}",
Method="GET")]
[OperationContract]
public Model.UserInfo GetUser(string id)
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.Get(new Guid(id));
}
[WebGet(UriTemplate = "/getall")]
[OperationContract]
public List<Model.UserInfo> GetAllUsers()
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.GetAll();
}
[WebGet(UriTemplate = "/deleteuser?id={id}")]
[OperationContract]
public void DeleteUser(string id)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Delete(new Guid(id));
}
[WebGet(UriTemplate = "/updateuser?user={user}")]
[OperationContract]
public void UpdateUser(string user)
{
XElement elem = XElement.Parse(user);
Model.UserInfo userInfo = new Model.UserInfo();
foreach (XElement e in elem.Elements())
{
switch (e.Name.LocalName)
{
case "FirstName": userInfo.FirstName = e.Value; break;
case "LastName": userInfo.LastName = e.Value; break;
case "ID": userInfo.ID = new Guid(e.Value); break;
}
}
BL.UserBL _objBL = new BL.UserBL();
_objBL.Update(userInfo);
}
}
}
WS
The Webservice is an item called “Web Service”. It has files “.asmx” and “.cs”. Additional project references: BL and Model.
The “.cs” file should contain the following code:
using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Collections.Generic;
/// <summary>
/// Summary description for OgieWS
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class OgieWS : System.Web.Services.WebService
{
public OgieWS()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public void AddUser(Model.UserInfo user)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Add(user);
}
[WebMethod]
public Model.UserInfo GetUser(Guid id)
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.Get(id);
}
[WebMethod]
public List<Model.UserInfo> GetAllUsers()
{
BL.UserBL _objBL = new BL.UserBL();
return _objBL.GetAll();
}
[WebMethod]
public void DeleteUser(Guid id)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Delete(id);
}
[WebMethod]
public void UpdateUser(Model.UserInfo user)
{
BL.UserBL _objBL = new BL.UserBL();
_objBL.Update(user);
}
}
Tester Projects
TesterRest
TesterRest project is a specific project calling the methods of REST project. It has an application configuration key called “ServiceURL” which contains the URL of the REST project. Additional references: Model.
TesterRest.cs contains:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Net;
using System.IO;
namespace TesterREST
{
public class TesterRest
{
public TesterRest()
{
}
public void AddNewUser(Model.UserInfo info)
{
string xmlUser = "";
XElement userInfo = new XElement("UserInfo",
new XElement("FirstName", info.FirstName),
new XElement("LastName", info.LastName),
new XElement("ID", new Guid())
);
xmlUser = userInfo.ToString();
Uri address = new Uri(string.Format("{0}adduser?user={1}", Settings1.Default.ServiceURL, xmlUser));
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
try
{
WebResponse response = request.GetResponse();
}
catch (WebException wex)
{
StreamReader reader = new StreamReader(wex.Response.GetResponseStream());
throw wex;
}
catch (Exception ex)
{
throw ex;
}
}
public List<Model.UserInfo> GetAllUsers()
{
List<Model.UserInfo> userCollections = new List<Model.UserInfo>();
XElement rootXml = XElement.Load(string.Format("{0}getall", Settings1.Default.ServiceURL));
foreach (XElement u in rootXml.Elements())
{
Model.UserInfo user = new Model.UserInfo();
foreach (XElement i in u.Elements())
{
switch (i.Name.LocalName)
{
case "FirstName": user.FirstName = i.Value; break;
case "LastName": user.LastName = i.Value; break;
case "ID": user.ID = new Guid(i.Value); break;
}
}
userCollections.Add(user);
}
return userCollections;
}
public Model.UserInfo GetUser(Guid id)
{
XElement rootXml = XElement.Load(string.Format("{0}getuser?id={1}", Settings1.Default.ServiceURL, id.ToString()));
Model.UserInfo user = new Model.UserInfo();
foreach (XElement i in rootXml.Elements())
{
switch (i.Name.LocalName)
{
case "FirstName": user.FirstName = i.Value; break;
case "LastName": user.LastName = i.Value; break;
case "ID": user.ID = new Guid(i.Value); break;
}
}
return user;
}
public void UpdateUser(Model.UserInfo info)
{
string xmlUser = "";
XElement userInfo = new XElement("UserInfo",
new XElement("FirstName", info.FirstName),
new XElement("LastName", info.LastName),
new XElement("ID", info.ID)
);
xmlUser = userInfo.ToString();
Uri address = new Uri(string.Format("{0}updateuser?user={1}", Settings1.Default.ServiceURL, xmlUser));
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
try
{
WebResponse response = request.GetResponse();
}
catch (WebException wex)
{
throw wex;
}
catch (Exception ex)
{
throw ex;
}
}
public void DeleteUser(Guid id)
{
Uri address = new Uri(string.Format("{0}deleteuser?id={1}", Settings1.Default.ServiceURL, id.ToString()));
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
try
{
WebResponse response = request.GetResponse();
}
catch (WebException wex)
{
throw wex;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
TesterWCF
TesterWCF project is a specific project calling the methods of WCF project. It has an application configuration key called “URLService” which contains the URL of the WCF project. It has 2 .cs files, TesterWCF.cs and SampleWCF.cs. The SampleWCF.cs is a proxy class generated by a tool by executing “svcutil.exe http://localhost:6969/SampleWCFLibrary/UserAddress.svc?wsdl”.
TesterWCF.cs contains:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Modelo;
namespace TesterWCF
{
public class TesterWCF
{
UserAddressClient client;
public TesterWCF()
{
}
public void AddUser(UserInfo user)
{
client = new UserAddressClient();
client.AddUser(user);
client.Close();
}
public UserInfo GetUser(Guid id)
{
UserInfo user = null;
client = new UserAddressClient();
user = client.GetUser(id);
client.Close();
return user;
}
public List<UserInfo> GetAllUsers()
{
client = new UserAddressClient();
List<UserInfo> userCollections = client.GetAllUsers().ToList<UserInfo>();
client.Close();
return userCollections;
}
public void UpdateUser(UserInfo user)
{
client = new UserAddressClient();
client.UpdateUser(user);
client.Close();
}
public void DeleteUser(Guid id)
{
client = new UserAddressClient();
client.DeleteUser(id);
client.Close();
}
}
}
TesterWS
TesterWS project is a specific project calling the methods of WS project. It has an application configuration key called “ServiceURL” which contains the URL of the WS project. It has 2 .cs files, TesterWS.cs and WSProxy.cs. The WSProxy.cs is a proxy class generated by a tool by executing “wsdl.exe http://localhost:6969/MyTestWS/MyWS.asmx?wsdl”.
TesterWS.cs contains:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TesterWS
{
public class TesterWS
{
WSProxy channel;
public TesterWS()
{
}
public void AddNewUser(UserInfo info)
{
channel = new WSProxy();
channel.AddUser(info);
}
public List<UserInfo> GetAllUsers()
{
channel = new WSProxy();
List<UserInfo> userCollections = new List<UserInfo>();
userCollections = channel.GetAllUsers().ToList<UserInfo>();
return userCollections;
}
public UserInfo GetUser(Guid id)
{
channel = new WSProxy();
UserInfo info = channel.GetUser(id);
return info;
}
public void UpdateUser(UserInfo info)
{
channel = new WSProxy();
channel.UpdateUser(info);
}
public void DeleteUser(Guid id)
{
channel = new WSProxy();
channel.DeleteUser(id);
}
}
}
To be continued..
As promised I will be providing a series of articles that could be beneficial for those individuals thinking to move on Windows Azure, I would like to share this study me and my Team made for finding the best communication options. Kudos for Rogelyn Chu (For the help on the study) and Michael Dorchain (For giving me the opportunity to work on this study).
Software architecture indeed needs a lot of careful study and analysis on the technology to use. This study is a vital component for us to identify whether this could be one of the core technologies we will implement on delivering the solution needed by our business. As times change and communication between systems has been the key factor of the success of implementing applications, this study could lead to solve this complexity and identify which would be the best solution for our design.
THE CHALLENGE: ONE PLATFORM FOR DIFFERENT KINDS OF COMMUNICATION
There’s no way around it: Different .NET Framework applications need different kinds of communication. Sometimes an application built using WCF needs to interact with code running on some other platform, such as a Java application server. The best choice here is frequently interoperable communication using SOAP, perhaps with one or more of the WS-* specifications. When a WCF application interacts with another WCF application, however, paying the performance price exacted by SOAP’s standard XML encoding isn’t necessary. A speedier binary encoding, one designed expressly for WCF-to-WCF communication, is a better choice. In other cases, the interaction style known as Representational State Transfer (REST) might be the right choice. More and more Internet applications provide a RESTful interface, for example, and so WCF applications must be able to communicate using this approach.
There are plenty of other possibilities, too. An application might need to send XML-defined data directly over HTTP, an approach that’s commonly known as Plain Old XML (POX). Perhaps that XML should be structured using common formats such as RSS and ATOM. Communication with a line-of-business application such as SAP might require an application-specific adapter. Queued messaging can be the best choice when reliable communication is required between occasionally connected systems. Similarly, the built-in peer-to-peer networking functions of Windows are the right solution for a certain class of problems, while some form of inter process communication, such as Windows named pipes, is required for interactions between software on the same machine.
Until relatively recently, each of these communication styles was supported with its own idiosyncratic platform. Developers were forced to learn a different programming model for each approach. WCF was created to change this, and as described next, it has.
But considering the fact that most of the .NET developers are still adjusted with the Web Services SOAP approach, we should not leave this out and take it into consideration. With that, we will also dig into the earlier approach of communicating via SOA since, web services are still one of the easiest applications to interact with other platforms.
Expectations on this Study
At the end of this study, it is expected that we will identify the best solution in terms of its effectiveness and efficiency using various factors like response time; bytes sent and received, and as well as cost economics. This study would also enable readers of this document to have an initial understanding of the technologies being evaluated.
Approach to the Study
The approach of this study would be a experimental approach to have a real basis of the conclusion of this paper. Since there are three subjects to be tested, we will be creating the three services in order for us to test and compare their performance and determine their strengths and weaknesses. The services would be a WCF Rest Service, a Web Service SOAP, and a WCF-WCF Binary communication. All services would be using the same Business Layer, Data Layer and Model; with this approach, we will be able to really identify which would be the best technology to use between them.
This study would basically focus only on Microsoft WCF REST, Microsoft Web Services SOAP and Microsoft WCF-WCF Communication tapping particularly the effectiveness and efficiency of the services. This would also include a forecast of how much cost we will incur if the services would be deployed on a cloud network.
In particular, this study would not be covering other services implementation offered by non-Microsoft Companies, deployment of services in a cloud network, windows azure and the likes, and full details of deployment guidelines and possible deployment plan.
Main Study
Lets say that on this study we will create a basic application that would utilize CRUD (Creat-Read-Update-Delete) functionalities on a single table Source named “UserProfile” which has 3 columns: “ID” (uniqueidentifier), “LastName” (varchar 200), and “FirstName” (varchar 200).
The methods are: “AddUser” (no return value), “UpdateUser” (no return value), “DeleteUser” (no return value), and GetAllUsers “List of UserProfile”.
We will be getting the following variables during the study: “Bytes Sent” (number of bytes sent in the request to the service), “Bytes Received” (number of bytes received in the response of the service), “Number of Calls” (the number of times in which a method needs to do to perform its function), and “Response Time” (the amount of time in milliseconds the request and response took place in a method of the service).
For checking the bytes send and received on this application, Fiddler2, Visual Studio 2008 and SQL Express 2005 was used in this study. You could get a copy of the tool at www.fiddler.com.
Here are the codes you need to recreate in order to come up with the test:
Data Layer
The Data Layer is also known as DataAccess project in this scenario. It will be called by Business Layer. It’s inheriting the “DataAccessBase” from DataHelper project. Additional project references: DataHelper and Model.




Business Layer
The Business Layer will call the Data Layer. Additional project references: DataAccess, Model and DataHelper.

On the next part of the article I will show you the Communication codes used for WCF REST, WS and WCF-WCF Communication.
I am so pleased to announce that Azure would start now to move to the Coordinated Universal Time staring March 8, 2009 at 10:00 AM GMT. This was based on the email I got from the Azure Services Platform Team.
Good news for a lot of developers then.
For those who have read my previous post, this is just a follow up blog for it. :)
I was reading an article on Windows Azure and was surprised to know that currently Azure is running on Pacific Standard Time. It's a good thing to know that soon, they will be migrating to Coordinated Universal Time (UTC). A good thing then for applications relying on local time.
When will Microsoft make the change?
As far as Microsoft is concerned, they will make this change soon. Most probably on the next few weeks. As of the moment, series of testings are being conducted within the community and these feedback would enable Microsoft to identify as to when the move would take place.
Why are they doing this?
Why not? Since Windows Azure is a global service platform, it is but right to have all applications inside the platform to behave the same way regardless of geographic conditions. It is but right to have windows Azure be consistent to all users worldwide. And if we are speaking of consistency, the standard choice now for timezone would be utilizing UTC.
What’s the potential impact to us?
Basically based on the blog I read regarding this, the following would be the impact of the migration to UTC.
- Occurence of gaps in the event logs if local timestamps would be used.
- Different results may occur if the UI of the application depend on the local timestamp.
- Some local timestamps stored already by the application may be interpreted differently on the move.
But design wise, a lot of applications now are utilizing UTC. But for those not yet utilizing this standard, you should take a look on the effects that might occur. For the others, your applications are safe.
Architecting services for Windows Azure basically
undertakes the following considerations:
- Cloud Services have specific
design considerations : always on, distributed state, large scale, failure
handling (you should expect failures and you should handle them)
- Windows Azure is an OS for
the Cloud : scale out, dynamic, and on-demand. Each machine runs its own
layer, but together this makes an OS
- Windows Azure manages
services not just servers : tell it what you want, it will help automate
the details
- Windows Azure frees
developers from many platform issues : you concentrate on application
logic instead of platform issues
How to
architect Windows Azure Services ?
Cloud
Computing is based on Scale-Out not scale-up. You can add / remove capacity on
demand. Pay for what you use as you go. Automation is key to reducing costs.
Design
considerations
-
Failure
of any given node (or role) should be expected : view each node (or role) as a
cache, state has to be replicated (don't assume your state is safe)
-
No
one-time install step : applications need to reinitialize on restarts. Do not
assume previous local state is available (If a node fails, we will try to
restart you)
-
Configuration
changes due to load or failures : handle dynamic configuration changes
-
Services
are always running (there is no maintenance window) : your code has to handle
upgrades or downgrades + your code must handle data schema changes
-
Services
are built using multiple nodes / roles : document service architecture,
document communication paths of elements
-
Services
can grow very large : state management will become difficult
ð Those issues are not new : you
have tried to be as stateless as possible.
If you have good design, Windows Azure will
manage your services, nodes and network. Windows Azure automates life cycle
management (Model Driven Automation).
Further readings can be found on this link.
First
of all, I would like to thank Risman for helping me out open this blog. I
would love to help this community get involved more on this technology and
bring Cloud Computing potentials to the Philippines.
So
before we define What's Windows Azure, let us first get a good understanding of
what is Cloud Computing.
So
let's say, we have an application and we wanted this application to be
available anywhere in the world regardless of platform then we definitely need
have a way to host this. Quoting on an article I saw in Wikipedia:
|
|
"Cloud computing is Internet ("cloud")
based development and use of computer technology ("computing").It
is a style of computing in which dynamically scalable and often virtualised
resources are provided as a service over the Internet. Users need not have
knowledge of, expertise in, or control over the technology infrastructure
"in the cloud" that supports them.
The concept incorporates infrastructure as a service (IaaS), platform as a
service (PaaS) and software as a service (SaaS) as well as Web 2.0 and other
recent (ca. 2008-2009) technology trends which have the common theme of
reliance on the Internet for satisfying the computing needs of the users.
Examples include Salesforce.com and Google Apps which provide common business
applications online that are accessed from a web browser, while the software
and data are stored on the servers."
|
So
Microsoft's move towards cloud computing pave the way to the birth of the Azure
Services Platform. So what is this platform?
|
|
The AzureTM Services Platform (Azure) is an
internet-scale cloud services platform hosted in Microsoft data centers,
which provides an operating system and a set of developer services that can
be used individually or together. Azure's flexible and interoperable platform
can be used to build new applications to run from the cloud or enhance
existing applications with cloud-based capabilities. Its open architecture
gives developers the choice to build web applications, applications running
on connected devices, PCs, servers, or hybrid solutions offering the best of
online and on-premises.
Azure reduces the need for up-front
technology purchases, and it enables developers to quickly and easily create
applications running in the cloud by using their existing skills with the
Microsoft Visual Studio development environment and the Microsoft .NET
Framework. In addition to managed code languages supported by .NET, Azure
will support more programming languages and development environments in the
near future. Azure simplifies maintaining and operating applications by
providing on-demand compute and storage to host, scale, and manage web and
connected applications. Infrastructure management is automated with a
platform that is designed for high availability and dynamic scaling to match
usage needs with the option of a pay-as-you-go pricing model. Azure provides
an open, standards-based and interoperable environment with support for
multiple internet protocols, including HTTP, REST, SOAP, and XML.
Microsoft also offers cloud applications ready for consumption by
customers such as Windows LiveTM, Microsoft DynamicsTM, and other Microsoft
Online Services for business such as Microsoft Exchange Online and
SharePoint® Online. The Azure Services Platform lets developers provide their
own unique customer offerings by offering the foundational components of
compute, storage, and building block services to author and compose
applications in the cloud.
|
Ok,
now I know most of you would say, we know that already and we have seen it at
the Web Ramp up event, how do I really start using it? The answer, it's just
creating the conventional way of web applications, difference is you just have
another way of creating packages for deployment in azure. And there are a lot of exciting features in Azure
that would be very beneficial to business and for us developers.
For
starters, I will repost the list of links I have sum up on one of the links in
the forums.
Visual
Studio development
Quick lap around VS2008 azure tools (very nice)
http://msdn.microsoft.com/en-us/library/dd203059.aspx
Development fabric & storage integration
http://msdn.microsoft.com/en-us/library/dd203061.aspx
Deployment
http://msdn.microsoft.com/en-us/library/dd203057.aspx
Azure training kit
http://www.microsoft.com/downloadS/details.aspx?FamilyID=413e88f8-5966-4a83-b309-53b7b77edf78&displaylang=en
Windows Azure Tools Development Fabric and Storage Integration
http://msdn.microsoft.com/en-us/library/dd203061.aspx
Integrating LiveID/AD into Azure projects
http://dev.live.com/blogs/devlive/archive/2008/11/12/432.aspx
Azure
SDK's
http://www.microsoft.com/azure/sdk.mspx
Azure
Azure management tools
http://code.msdn.microsoft.com/AzureManagementTools
Live services poster
http://dev.live.com/liveframework/livefxposter.pdf
Whitepapers
Azure services platform
http://download.microsoft.com/download/e/4/3/e43bb484-3b52-4fa8-a9f9-ec60a32954bc/Azure_Services_Platform.docx
Azure blobs
http://go.microsoft.com/fwlink/?LinkId=131258
Azure Tables
http://go.microsoft.com/fwlink/?LinkId=131257
Azure
Services Platform Videos
Windows
Azure "How Do I" Videos
How Do I:
Get Started Developing with Windows Azure?
http://msdn.microsoft.com/en-us/azure/dd327648.aspx
How Do I: Deploy a Windows Azure Application?
http://msdn.microsoft.com/en-us/azure/dd327644.aspx
How Do I:
Store Blobs in Windows Azure Storage?
http://msdn.microsoft.com/en-us/azure/dd327650.aspx
How Do I:
Leverage Queues in Windows Azure?
http://msdn.microsoft.com/en-us/azure/dd464806.aspx
Debugging
Tips for Windows Azure Applications
http://msdn.microsoft.com/en-us/azure/dd464807.aspx
How Do I:
Store Data in Windows Azure Tables?
http://msdn.microsoft.com/en-us/azure/dd483299.aspx
.NET
Services "How Do I" Videos
How Do I:
Get Started with .NET Services?
http://msdn.microsoft.com/en-us/azure/dd441704.aspx
How Do I:
Harness the Microsoft .NET Service Bus?
http://msdn.microsoft.com/en-us/azure/dd441706.aspx
Live
Services "How Do I" Videos
How Do I:
Get Started with the Live Framework?
http://msdn.microsoft.com/en-us/azure/dd425068.aspx
How Do I:
Use the Microsoft Live Framework Resource Browser?
http://msdn.microsoft.com/en-us/azure/dd441707.aspx
So
with these references to start with, are we ready now? I hope you are. Since I have prepared myself now to take the
leap on the next level of cloud computing starting with the Azure Services
Platform.