| More
.NET - Page 2
 


Top 10 Things Seasoned .NET Developers Understand or 10 Things New .NET Developers Need to Know

My coworker at Intertech (Jim White) wrote an interesting blog post which addressed the "10 topics advanced Java programmers need to know" (he's a Java-guy, but don't hold that against him ;-). I liked his article, so I thought I'd offer up a .NET version of the same post.  Here it goes, and thanks Jim for the idea!  By the way, these are *not* any any specific order...

10) LINQ

At first, LINQ was seen by many to be a interesting shortcut for grabbing data from a container.  Nowadays however, LINQ is everywhere.  LINQ to XML, LINQ to EF, PLINQ and LINQ to Objects are common place.  If you want to show your team mates you are up to speed on core .NET technologies, understanding LINQ should be on the top of your list of ToDos.

9) WPF (and therefore Silverlight)

Regardless if you are a "Web Person" or a "Desktop Person", Microsoft's current GUI APIs are quickly replacing older frameworks, especially Windows Forms.  Both WPF and Silverlight use the same core body of tech, so when you understand 1, the other is close behind.

8) The Blend IDE

I was a man who was fearful of Blend early on.  In fact, I wore my fingers to the bone typing in XAML by hand.  Trust me, if I can get over the Blend fear-zone, any one can.  If you are doing WPF or Silverlight, usnig Blend makes your work much easier, especially when working with templates, animations or graphics.

7) TPL

The Task Parallel Library is a new .NET 4.0 threading / multicore API.  Using TPL (and PLINQ) you can very easily add multithreaded functionality to your applications, using a framework which hides a good number of the low level details. Thanks thread pool!

6) Lambdas

The C# => operator, or the VB Sub/Function statements, can seem to be quite terse at first glance. However, lambdas are a great shortcut for working with delegates.  If you are serious about learning LINQ and the TPL, you *need* to be confortable with lambdas.

5) WF 4.0

OK, I know.  WF 3.0-3.5 had some warts.  But honest, WF 4.0 is a massive step in the right direction.  A whole new assembly stack, new designers, new engine and new activities make the process of modeling business processes clean and simple.  And, WF 4.0 is based on XAML!

4) Knowing if you REALLY need That Pattern

Design patterns *can* help you write easy to maintain code....or they can add layers of unnecessary complexity.  We programmers love the latest and greatest to be sure, but I have seen too many people cram patterns into projects that just don't need them.  Case in point?  ASP.NET MVC.  Yes, it is great for testing web sites, but there are ways to do so without MVC.  Don't use a pattern because it is the latest buzz word.  Use it because it will make your life better.

3) ADO.NET EF

The Entity Framework is a slick object model over relational database logic, which favor LINQ queries over T-SQL queries. While the connected and disconnected layers are certainly still part of the picture, the EF model can really simplify common database activities....and the VS 2010 designers are very solid.

2) Use of Dynamic Data

The DLR allows you to opt-into scripting like functionality, within a statically typed language. If you are doing any sort of COM interop, dynamic assembly generation or reflection tasks, dynamic data can reduce the amount of code you will need to write by a *great* deal.  Just watch your typing...

1) The .NET Type System

In a rush to get software out the door ASAP, many programmers "skip" over the foundational nuts and bolts, and google for the next "how do I make my grid look like this" sort of answer.  Google is great, but you really owe it to yourself to be solid on the ins and outs of classes, interfaces, structures, enums and delegates. These are the bread and butter aspects of every possible .NET application and API.

So, thanks again Jim for the idea. Hope to see some of you in class where we can learn about these (and many other) .NET topics

 


Posted by: Andrew Troelsen
Posted on: 6/7/2010 at 4:47 PM
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (3) | Post RSSRSS comment feed

Windows Azure Table Storage vs. Windows SQL Azure

By Jim White (Director of Training and Instructor)

Last week, my fellow Intertech colleague and Microsoft MVP, Tim Star, and I presented the Windows Azure Bootcamp for the Twin Cities.  According to Microsoft reps, we broke the record for the most attended bootcamp in the US with nearly a hundred people at the event.

A common question that I received during and after the bootcamp was "Why would I want to use Windows Azure Table Storage versus Windows SQL Azure to store my application data?"  A good question with the answer dependent on your application and data needs.

Table Storage and SQL Azure Defined

First, allow me to backup and set the stage a little for this discussion.  SQL Azure is essentially SQL Server in the Microsoft cloud computing environment known as Azure.  That is not quite true in that SQL Azure currently has a number of limitations and unsupported features that SQL Server 2008 has (here is a starter list of limitations:  http://msdn.microsoft.com/en-us/library/ee336245.aspx).  I like to say that SQL Azure is either SQL Server 2008 minus or SQL Express plus depending on how you want to view it.  Table Storage is one of three alternate storage mechanisms built into Azure that is collectively called Windows Azure Storage Services.  The other two being queues and blobs.  Table Storage allows you to store serialized entities in a table, but the term table here  is not a relational database table.  To provide people with some analogy they can use to get their arms around Table Storage, I like to tell people to think of Table Storage as a fancy spreadsheet.  You can store the state of your entities in the columns of the spreadsheet.  However, there is no linkage or relationship (therefore joins) between entities - at least none that is automatically managed and maintained by Azure.  There are no custom indexes - at least not today.

Interestingly, when Azure was first introduced in 2008, SQL Server was not part of the original picture.  Because of developer negative reactions, SQL Azure was added to the next preliminary release in 2009.  There is a growing faction that is trying to get the software community to look at SQL alternatives.  The "No-SQL" community (see here and here), to some extent, has influenced part of the Azure cloud computing platform through the Table Storage option, but not enough to eliminate it from the Microsoft cloud.

While both SQL Azure and Azure Table Storage provide data persistence via table structure, there are a number of differences between them.  The sections below outline some of the key differences and factors you want to weigh before building an application for Azure that requires some form of table persistence.

Scale and Performance

When looking at sheer volume, Table Storage is today far more scalable than SQL Azure.  Given a storage account (storage accounts hold blobs, queues and tables) is allowed to be 100TB in size, in theory your table could consume all 100TB.  At first glance, a 100TB chunk of data may seem overwhelming.  However, Table Storage can be partitioned.  Each partition of Table Storage can be moved to a separate server by the Azure controller thereby reducing the load on any single server.  As demand lessens, the partitions can be reconsolidated.  Reads of Azure Table Storage are load balanced across three replicas to help performance.

Entities in Table Storage are limited to 1MB each with no more than 255 properties (3 of which are required partition key, row key, and timestamp).  That seems like an absurd number, and it is, but remember that there are no relationships and joins in Table Storage.  Therefore, you might need some wide tables to handle associated data.

Today, SQL Azure databases are limited to 1GB or 10GB.  However, sometime this month (June 2010), a 50GB limit is supposed to be available.  What happens if your database is larger than 10GB today (or 50GB tomorrow)?  Options include repartitioning your database into multiple smaller databases or sharding (Microsoft's generally recommended approach).  Without getting into the database details of both of these database design patterns, both of these approaches are not without issue and complexity, some of which must be resolved at the application level.

Data Access

Data in the cloud, be it in SQL Azure or Azure Table Storage, can be accessed from in or out of the cloud.  To access data in SQL Azure, all the standard tools and APIs apply that work with SQL Server.  Meaning, your existing .NET/SQL Server knowledge and experience can be heavily leveraged.  ADO.NET and ODBC APIs can be used by application code to access the SQL Azure database.  Tools like SQL Server Management Studio and Visual Studio can be pointed to the SQL Azure instance and manipulate the schema and data just as you do today with SQL Server. 

Access to Azure Table Storage is accomplished either via REST API or Storage Client Library provided with the Windows Azure SDK.  Using the REST API allows client applications to communicate and use data from Table Storage without having detailed and specific knowledge of an Azure API, but it is more complex and difficult to work with.  The Storage Client Library (which leverages LINQ to Objects) provides a layer of convenience but requires the application reference the Storage Client Library APIs.  REST and the Storage Client Library incur a learning curve that is typically not there when using SQL Azure.

Portability

As mentioned, data in SQL Azure and Table Storage can be accessed from applications in and out of the cloud.  That means applications can be moved in or out of the cloud and still deal with the data in the cloud in the same way.  However, one question that may need to be considered is whether the data must always live in the cloud?  Applications generally view data in SQL Azure similar enough to data in a normal SQL Server database as to allow the data to migrate back and forth between the cloud and on-premise databases.  In fact, there are even migration tools to help move data between instances of SQL Server and SQL Azure. 

However, given the unique nature and access APIs of Table Storage, portability of the data is not as straight forward.  Table Storage tightly couples your data to the cloud.  Moving the data out of the cloud would require an on-premise data storage alternative, a data migration strategy, and likely require application code changes.

Transactions and Concurrency

SQL Azure supports typical ACID transactions for work within the same database.  Transactions across databases are not supported.  SQL Azure allows for typical optimistic and pessimistic concurrency strategies.

Table Storage supports transactions for entities in the same table and table partition, but not across tables or partitions.  Additionally, only 100 operations or less (what is called a batch in Azure Table Storage) can be part of the transaction.  Only one operation can be performed on each entity in the batch, and the batch must be limited to 4MB.  Table Storage abides strictly by an optimistic concurrent strategy.  If, on commit of the transaction, data has been changed by another process the whole transaction must be rolled back and retried.  Due to this single concurrency strategy, a built-in retry option is provided with the Storage Client Library.

Queries

Using Table Storage, queries are limited to 1000 entities by default.  If more than 1000 entities are found, a continuation token is returned and must be used by the application to retrieve the next set of entities.  Queries that take longer than 5 seconds also return a continuation token.  Queries that take longer than 30 seconds are cancelled.  Data in Table Storage is organized by partition key and indexed by row key.  Because there are no custom indexes in tables, queries by partition key and row key are fast, but queries that do not use partition key and row key are slow.

Generally speaking, SQL Azure has no limitations, issues or special programming requirements to work with large queries.  Good database and index design can help improve performance of queries; especially large ones.

Column types

Columns in Table Storage are limited to the types in the table below.

byte[]
bool
DateTime
double
Guid
Int32 or int
Int64 or long
String

Cost

Perhaps the most unique aspect to designing and architecting applications for the cloud is that it requires developers to think like businessmen.  Each technical choice often has direct costs associated with it when developing for the cloud.  The choice in data storage can have a huge impact on the cost of running an application.

Azure Table Storage costs 15? per GB of storage per  month.  Additionally, you pay 1 cent per 10,000 transactions with Table Storage.  SQL Azure costs are $9.99 for 1 GB of storage per month ($99.99 for 10GB). 

See Microsoft's sight for more details and specifics on costs here.

Bottom Line

Chris Hay and Brian Prince in their forth coming book Azure in Action (published by Manning - see here) provide a synopsis of the SQL Azure vs. Table Storage in a few paragraphs.  "If size is the issue, that would be the first flag that you might want to consider Azure Tables. As long as the support Tables has for transactions and queries meets your needs. The size limit surely will, at 100TB."  Further they suggest sophisticated transactions, or a complex authorization model might require the services of SQL Azure.  And as shown by the cost table above, "The final consideration is cost. I can store a lot of data in Azure Tables for a lot less money than I can in SQL Azure. SQL Azure is giving me a lot more features to use (joins, relationships, etc.), but it does cost more."

Future

We are given every indication by Microsoft that SQL Azure will have far more capability in the future - akin to the SQL Server you might find in your data centers today.   So some of the comparison above may be moot or less important over time.  Additional functionality is also being proposed to Table Storage as well.  For example, support of secondary (non-key) indexes is already been suggested for a future release (see here).  However, key architectural differences between SQL Azure and Table Storage will remain and leave application designers having to pick the best option for their systems.  Welcome to cloud computing.  There is a lot of ROI to be had by running in the cloud, but only with proper application design and architecture.

If Intertech can help you  negotiate the issues of cloud computing, please contact Ryan McCabe at ryan.mccabe@intertech.com.


Posted by: Jim White
Posted on: 6/1/2010 at 5:34 PM
Tags: , , ,
Categories: Cloud Computing | .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

A Review of VB Event Handling (WithEvents, AddHandler and AddressOf)

When you are building an application using VB, you will most certainly need to hook into various event sources.  While events are very common when you are constructing a GUI application (WPF, ASP.NET, Windows Forms), they are also very important for non-UI tasks such as working with threads, callbacks from database operations, and other tasks.

As it turns out, VB has a few "oddities" regarding how to hook into a given event, so I wanted to do a quick blog post which will hopefully clarify our choices.

First of all, when you are declaring a field of a Class, Structure or Module, you have the option of making use of the WithEvents keyword.  When you do so, you are able to selectively hook into events of interest using the Handles clause on a given class method. One part of this puzzle which is hidden from view is the fact that each and every .NET event is defined in termes of a related delegate.  As you may know, the .NET delegate type allows us to capture, in a strongly typed manner, the address of another method. Given this point, the method that uses the Handles clause must match the underlying delegate definition, or you will receive compile time errors!

Here is a simple example of capturing the Click event of the Windows Forms Button class.  Take note that the method receiving the event notification takes an Object as the first parameter, and a EventArgs as the second, given that the Click event has been defined in terms of a system delegate named System.EventHandler.

 Class MainWindow
 
Inherits Form

  ' Inform the Button we are interested in listening to
  ' events.
  Private WithEvents btnClickMe As Button

  Public
Sub New()
    btnClickMe =
New Button With {.Height = 100,
      .Width = 100, .Text =
"OK!"}
   
Me.Controls.Add(btnClickMe)
  End Sub

  Private Sub btnClickMe_Click(ByVal sender As Object,
   
ByVal e As System.EventArgs) Handles btnClickMe.Click
   
MessageBox.Show("Clicked!")
 
End Sub
End
Class

Now, one gotchya is that the WithEvents keyword can only be used for fields (local variables need not apply). When you wish to handle an event for a local variable, you are required to use the AddHandler statement.  Here, you will specify the event name and method to call (via the AddressOf operator).  However, in this case the Handles clause is not used.  Here is a re-working of the previous class which illustrates these points: 

Class MainWindow

Inherits Form
 
Public Sub New()
   
Dim btnClickMe As Button
   
btnClickMe = New Button With {.Height = 100,
      .Width = 100, .Text =
"OK!"}

   
AddHandler btnClickMe.Click, AddressOf btnClickMe_Click
    
Me.Controls.Add(btnClickMe)
 
End Sub
...
End Class

Of course, with the release of .NET 4.0, VB has full support for lambda expressions.  This is yet another way to hook into event sources, which was covered in a previous blog post.


Posted by: Andrew Troelsen
Posted on: 6/1/2010 at 10:03 AM
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

C# and the .NET Platform, 5th Ed.

Quick blog post this week to let people know that the 5th Edition of my C# book is in the stores!

C# 2010 and the .NET 4.0 Platform tops in at more than 1700 pages (eek!).

But there are a number of new topics, extended topics, additional examples and other goodies. Here is a hit list of the big topics:

  • Coverage of the C# dynamic keyword and DLR
  • Coverage of the ADO.NET Entity Framework / LINQ to Entities
  • Coverage of C# 2010's improved COM interop
  • Coverage of the TPL and PLINQ
  • Deeply expanded coverage of WPF
  • Deep coverage of Expression Blend
  • Coverage of WF 4.0 (which is totally different from the previous WF API)
  • The new WCF 4.0 bits.
  • etc, etc, etc.

As before, Apress is offering deals for a digital copy of the book if you buy the printed copy.  Check out the following link for more details.

Be back next week with some new tech-posts.  Thinking of starting a long blog tutorial about Expression Blend......hummmm.....

Happy coding,

Andrew

 


Posted by: Andrew Troelsen
Posted on: 5/21/2010 at 3:14 PM
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Simple COM Interop with Dynamic

The C# 2010 dynamic keyword can be used for a variety of reasons, some of which are a tad esoteric.  However, there is a very practical use of this new language feature, specifically the (radical) simplification of COM interop programming. By default, when you import a COM library into a VS 2010 project (configured to target .NET 4.0), every COM VARIANT is automatically mapped to a dynamic data type.

This behavior greatly decreases the need to cast data types and drill into low level interop primitives (such as the underlying get_ / set_ methods).

Furthermore, thanks to C# 2010 optional arguments, you no longer need to author reams of Type.Missing tokens when specifying missing values.

To showcase the distinction, assume you wish to map some data in a List to Microsoft Excel.  Before .NET 4.0, you might author code such as the following:

Code Snippet
  1. static void ExportToExcel2008(List<Car> carsInStock)
  2. {
  3.     Excel.Application excelApp = new Excel.Application();
  4.  
  5.     // Must mark missing params!
  6.     excelApp.Workbooks.Add(Type.Missing);
  7.  
  8.     // Must cast Object as _Worksheet!
  9.     Excel._Worksheet workSheet = (Excel._Worksheet)excelApp.ActiveSheet;
  10.  
  11.     // Must cast each Object as Range object then call
  12.     // call low level Value2 property!
  13.     ((Excel.Range)excelApp.Cells[1, "A"]).Value2 = "Make";
  14.     ((Excel.Range)excelApp.Cells[1, "B"]).Value2 = "Color";
  15.     ((Excel.Range)excelApp.Cells[1, "C"]).Value2 = "Pet Name";
  16.  
  17.     int row = 1;
  18.     foreach (Car c in carsInStock)
  19.     {
  20.         row++;
  21.         // Must cast each Object as Range and call low level Value2 prop!
  22.         ((Excel.Range)workSheet.Cells[row, "A"]).Value2 = c.Make;
  23.         ((Excel.Range)workSheet.Cells[row, "B"]).Value2 = c.Color;
  24.         ((Excel.Range)workSheet.Cells[row, "C"]).Value2 = c.PetName;
  25.     }
  26.  
  27.     // Must call get_Range method and then specify all missing args!.
  28.     excelApp.get_Range("A1", Type.Missing).AutoFormat(Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2,
  29.             Type.Missing, Type.Missing, Type.Missing,
  30.             Type.Missing, Type.Missing, Type.Missing);
  31.  
  32.     // Must specify all missing optional args!  
  33.     workSheet.SaveAs(string.Format(@"{0}\Inventory.xlsx", Environment.CurrentDirectory),
  34.         Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  35.         Type.Missing, Type.Missing, Type.Missing);
  36.     excelApp.Quit();
  37.     MessageBox.Show("The Inventory.xslx file has been saved to your app folder", "Export complete!");
  38. }

Notice in particular the grimy casting operations (Excel.Range, and so forth). 

Now, here is the same code once again, using the new features of C# 2010:

Code Snippet
  1. static void ExportToExcel(List<Car> carsInStock)
  2. {
  3.     // Load up Excel, then make a new empty workbook.
  4.     Excel.Application excelApp = new Excel.Application();
  5.     excelApp.Workbooks.Add();
  6.  
  7.     // This example uses a single workSheet.
  8.     Excel._Worksheet workSheet = excelApp.ActiveSheet;
  9.  
  10.     // Establish column headings in cells.
  11.     workSheet.Cells[1, "A"] = "Make";
  12.     workSheet.Cells[1, "B"] = "Color";
  13.     workSheet.Cells[1, "C"] = "Pet Name";
  14.  
  15.     // Now, map all data in List<Car> to the cells of the spread sheet.
  16.     int row = 1;
  17.     foreach (Car c in carsInStock)
  18.     {
  19.         row++;
  20.         workSheet.Cells[row, "A"] = c.Make;
  21.         workSheet.Cells[row, "B"] = c.Color;
  22.         workSheet.Cells[row, "C"] = c.PetName;
  23.     }
  24.  
  25.     // Give our table data a nice look and feel.
  26.     workSheet.Range["A1"].AutoFormat(
  27.         Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
  28.  
  29.     // Save the file, quit Excel and display message to user.
  30.     workSheet.SaveAs(string.Format(@"{0}\Inventory.xlsx", Environment.CurrentDirectory));
  31.     excelApp.Quit();
  32.     MessageBox.Show("The Inventory.xslx file has been saved to your app folder", "Export complete!");
  33. }

Nice, eh? I'm sure you'd agree that simplification is always a good thing...


Posted by: Andrew Troelsen
Posted on: 5/16/2010 at 8:59 PM
Tags:
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Executing SQL Scripts with Oracle.ODP

A useful but not widely publicized feature of the Oracle.ODP database provider for .NET is the ability to execute SQL scripts as a single command. It's quite easy to use the capability but there are a few caveats that are worth being aware of to save time and frustration.

Let's start by looking at a simple example of executing a single SQL statement using ODP:


using
System.Configuration; using Oracle.DataAccess.Client; namespace OracleODP { public class
SingleStatementSample { public static void Main(string[] args) { var sql = "INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( 123, 'HELLO WORLD' )"; var connString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; using (var conn = new OracleConnection(connString)) using (var command = new OracleCommand(sql, conn)) { conn.Open(); command.ExecuteNonQuery(); } } } }

Nothing terribly surprising here. We get a connection string from configuration, create a new OracleConnection, and a new OracleCommand with a simple INSERT statement as the command text.

So how do we run multiple statements in a single command? Well, a reasonable first guess may be to add multiple statements directly to our SQL string and separate them with the typical ";" separator:


var
sql =
@"INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( 123, 'HELLO WORLD' ); INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( 456, 'HELLO AGAIN' );";

Unfortunately, this won't work with Oracle; try it and you'll get an error that looks something like:


Oracle.DataAccess.Client.OracleException: ORA-00911: invalid character.

Informative, isn't it? Fortunately, the solution is quite simple: surround the statements in an anonymous PL/SQL block:


var
sql =
@"BEGIN INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( 123, 'HELLO WORLD' ); INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( 456, 'HELLO AGAIN' ); END;";

Can it really be that simple? Well, yes ... and no. Using anonymous blocks comes with some considerations that you should be aware of.

Line Break Considerations

Surprisingly, Oracle can be quite picky about what characters it accepts as legitimate line breaks. In Windows, a line break is typically a carriage return (CR), line-feed pair (LF) pair; while on Unix and Linux platforms, line breaks are represented just by a carriage return. Unfortunately, depending on where your script content originates, you may inadvertently have CR/LF pairs in it. Most often, this would be the case if you read your SQL script from a file or an embedded resource - where the normal encoding would use CR/LF. 

Unfortunately, the error message you get from Oracle isn't very helpful if you run into this situation:


Initialization method Tests.AnonymousBlock.TestScript threw exception:
Oracle.DataAccess.Client.OracleException:
Oracle.DataAccess.Client.OracleException: ORA-06550: line 1, column 6:
PLS-00103: Encountered the symbol "" when expecting one of the following: begin case declare exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe.

While I haven't been able to find any definitive documentation, empirical testing shows that Oracle will accept a CR as line break but not necessarily a CR/LF pair. To be safe, I replace CR/LF pairs with CRs before using them:


command.CommandText = sql.Replace("\r\n", "\n");
DDL vs. DML Considerations

Another factor that can come into play is when trying to execute DDL statements in a PL/SQL block rather than DML statements. DDL consists of statements that describe or modify data structure rather than their contents. Oracle does not support executing DDL statements directly within an anonymous block. Surprisingly, some statements that you may think are DML are actually DDL - the best example of this the TRUNCATE command:


TRUNCATE TABLE
IBS_ROUTED_EVENT;

The above code looks like regular data manipulation language, but it's actually DDL and cannot be executed in an anonymous block. If you try you'll get something like:


Oracle.DataAccess.Client.OracleException: Oracle.DataAccess.Client.OracleException: ORA-06550: line 4, column 12: PLS-00103: Encountered the symbol "TABLE" when expecting one of: := . ( @ % ;

...another case of a less than helpful error message. Fortunately, all is not lost. It's possible to execute DDL within an anonymous block using the EXECUTE statement:


EXECUTE IMMEDIATE
'TRUNCATE TABLE IBS_ROUTED_EVENT';

The DDL statements in Oracle include: ALTER, COMMENT, CREATE, DROP, RENAME, REPLACE, and TRUNCATE. The EXECUTE IMMEDIATE statement accepts a dynamic SQL statement as a string, hence the need for single quotes around the SQL to run.

One important consideration when executing DDL (whether in an anonymous block or otherwise) is that DDL always performs in implicit commit. This is a critical fact to keep in mind - when you execute DDL any pending work will automatically be committed. Once this happens, you cannot roll back or undo anything prior to the DDL statement. Consequently, I generally advise developers to avoid using DDL in SQL - there's usually a better alternative.

Returning Values From Anonymous Blocks

The last topic we will look at is how to return results from an anonymous block. It turns out, Oracle.ODP makes this relatively easy, if a bit unintuitive.

The OracleCommand class allows parameters to be attached to the executed statement - parameters may be either input, output, or both. Adding a parameter can be done directly through the OracleCommand object. Here's an example that uses both input and output parameters:


public static void Main(string[] args) { var sql =
@"BEGIN INSERT INTO TEST_TABLE( NKEY, STEXT ) VALUES( SEQ1.NEXTVAL, :value1 ) RETURNING NKEY INTO :key;
END;"
; var connString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; using (var conn = new OracleConnection(connString)) using (var command = new OracleCommand(sql, conn)) { conn.Open();
// add parameters var p1 = command.Parameters.Add(":value1", "Hello World"); // make the :key parameter an output param var p2 = command.Parameters.Add(":key",null); p2.Direction = ParameterDirection.Output; p2.OracleDbType = OracleDbType.Int32; command.ExecuteNonQuery(); // print the returned value... Console.WriteLine("The new record's key is {0}", p2.Value); } }

The example above uses the RETURNING ... INTO ... syntax to allow a sequence-assigned value to be returned to the caller. This is a useful technique that allows any value computed at the database to be returned to your .NET code. Sweet!

Why Execute Statements as a Script?

Now that we've looked at how we can execute SQL scripts, let's take a brief look at why we may choose to do so. Executing multiple SQL statements as a script offers a number of advantages:

  • It performs all of the work in a single trip to the database
  • It automatically treats all of the work as a single transaction
  • It simplifies the .NET code you write to execute several commands
  • It allows bind variables to apply to multiple statements
  • It allows results of a computation or SQL operation to be cached
  • It allows you to mix regular SQL with PL/SQL statements

Most of these benefits should be self-explanatory - but a few deserve a little more.

When code is combined into a single anonymous block, any bind variable are available in all SQL statement within that block. As a result, it's possible to reuse a single bind variable - which simplifies both the SQL code and the .NET code that prepares and executes it. If you do choose to reuse bind variable, make sure that they are input-only. Output bind variables cannot be reused.

An anonymous blocks may optional include declarations of local variables - variables that may be initialized or set by statements within the block. Not to be confused with bind variables, local variables must be defined in their own DECLARE section which appears before BEGIN:


DECLARE
-- declare record variable dept_rec dept%ROWTYPE; -- declare cursor variable CURSOR c1 IS SELECT ename, sal, hiredate, job FROM emp; -- declare simple variable empSalary REAL(7,2);

Mixing SQL and PL/SQL in an anonymous block is convenient, however, generally what we want to do is repeat the same operation several times with different values. An example is inserting several records into the database in one trip. While we can do this by expanding the SQL directly into the anonymous block, a better approach is to use array binding to pass multiple parameters to the database. This technique will be the topic of a future blog post. For now, take a look at the linked Oracle article, and keep in mind that bind variables are the preferred technique to pass parameters to Oracle - they reduce SQL injection risks and allow the database to avoid parsing SQL statements over and over again.

The Wrap Up

So let's review what we've learned :

  1. Oracle ODP allows you to execute multiple statements together in a single database using an anonymous block.
  2. Anonymous blocks are sensitive to line-break encoding, so replace your CR/LF pairs within a single CR character to avoid problems.
  3. Anonymous blocks support mixing SQL and PL/SQL statements, and can even include DDL statements using the EXECUTE IMMEDIATE.
  4. Anonymous blocks can use local variables defined in the DECLARE section, allowing expensive data to be computed once and cached.
  5. Anonymous blocks support both input and output parameters, allows results to be returned back to the caller.

del.icio.us Tags: ,,,,,

Posted by: Leo Bushkin
Posted on: 5/11/2010 at 4:09 PM
Tags: , , ,
Categories: .NET | General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Silverlight on Linux

Microsoft has been pushing the Silverlight API at a blistering pace. It seems like only yesterday we were building SL 2.0 applications.  SL 3.0 came and vanished with the blink of an eye, as 4.0 is upon us. 

One aspect of Silverlight which makes developers quite pleased is that it does run just fine under Mac OS X, which certainly helps increase the market use. However, as far as Microsoft is concerned, Linux users are out of luck.

Thankfully, the Mono team has developed (and is developing) an open source alternative to Silverlight called Moonlight. This API is compatible with Microsoft Silverlight 2.0, and allows developers to build and deploy their Silverlight enabled web pages to Linux machines (provided the user has installed the Moonlight runtime).

The final release of Moonlight 2.0 supports Deep Zoom, and all features of SL 2.0

Moonlight 3.0 and Moonlight 4.0 (which support the feature set of Silverlight 3.0 and 4.0) are currently in development.  

Also, the MonoDevelop IDE (which runs under Windows, Mac and Linux) provides various Moonlight templates. 

So the short answer is Silverlight does run on Linux, with a little help from the fine folks at the Mono project. 

Happy coding. 


Posted by: Andrew Troelsen
Posted on: 4/28/2010 at 10:26 AM
Tags:
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Windows Azure Local File Storage - How To Guide and Warnings

By Jim White (Intertech Director of Training and Instructor)

In general, Microsoft has tried to make writing Web applications for the Azure platform akin to writing for your local IIS environment.  In fact, Microsoft lists "use your existing development skills to build cloud applications" on the Azure Web site as one of its major selling points.  I think, to a large extent, .NET developers will find building or moving an application to Azure straightforward.  However, to be fair, there are also a number of areas where the application will change to deal with the reality of this new platform and, more generally, cloud computing.  One of those areas is simple file access and/or local storage.

File Access in the "Normal" ASP.NET world

For example sake, say you needed to read/write from a simple text file.  Perhaps you need to read some configuration information from the file, or perhaps some SQL that you need to execute was in the file.  Whatever the reason, accessing this file is pretty straightforward.  In a "normal" ASP.NET application, accessing a file that is stored on a virtual path on the Web server is quite simple and might look like the code below (in C#).

    //----------------------- read config contents --------------------------------
    try
    {
        string s = System.IO.File.ReadAllText(Server.MapPath("myConfigs") + "myFile.txt");
        //... do your work with s
    }
    catch (Exception myException)
    {
       ...    }

    //----------------------- write config contents --------------------------------
    if (!text.Equals(""))
    {
        System.IO.File.WriteAllText(Server.MapPath("myConfigs") + "myFile.txt", text);
    }
    else
    {
        System.IO.File.WriteAllText(Server.MapPath("myConfigs") + "myFile.txt", "no data");
    }

File Access in the Cloud

Now, how would that look in the cloud?  Well, first you must step back and consider that local storage in the cloud is not the same as that under our local IIS environment.  Local storage, is assumed under an ASP.NET application running on a local IIS server.  In the Azure world, you must first configure your role to request local storage as it is deployed.  This can be done with the Role Editor in VS 2008.  The Local Storage tab on the editor allows you to specify the name, size and clean/role policy for the storage as shown below.

image The information from this editor is stored in the service definition file of the role and used to configure the Azure environment when the application is published to the cloud.

Local Storage Location

So now you have local storage, but where is it?  When you deploy your application (consisting of either a web or worker role) to Azure, a storage area is assigned to your application.  The exact location is at the Azure servers discretion.  The physical path of the folder for your assigned storage can be located through the Azure API.  In this case, request the location of your local storage through, Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.  The RoleEnvironment class represents the Azure environment that your instance of your role (web or worker) is running in.  So, reading and writing to that file might look something like the following code in an Azure world.

    //----------------------- read config contents in Azure -----------------------
    try
    {

            LocalResource myConfigsStorage = RoleEnvironment.GetLocalResource("myConfigs");

        string s = System.IO.File.ReadAllText(myConfigStorage.RootPath + "myFile.txt");
        //... do your work with s
    }
    catch (Exception myException)
    {
        ...    }

    //----------------------- write config contents in Azure------------------------
    if (!text.Equals(""))
    {

           LocalResource myConfigsStorage = RoleEnvironment.GetLocalResource("myConfigs");

        System.IO.File.WriteAllText(myConfigStorage.RootPath + "myFile.txt", text);
    }
    else
    {
        System.IO.File.WriteAllText(myConfigStorage.RootPath + "myFile.txt", "no data");
    }

Easy enough you say.  Yes, the API is straightforward enough so as to appease most .NET developers.  However, a bigger issue with regard to this local storage must be considered.

Local Storage is Temporary and Instance Relative in the Cloud

Local storage, like that just used in the example to read/write text to myFile.text is temporary in Azure!  So, if the virtual machine supporting your role dies and cannot recover, your local storage is lost!  Therefore, Azure developers will tell you, only volatile data should ever be stored in local storage of Azure.  Furthermore, I eluded earlier to the fact that the storage was per instance of a role.  Importantly, local storage is not shared across multiple role instances.  Usually, people move applications to the cloud to take advantage of the scalability and redundancy multiple instances provide.  But these instances each have their own local storage and cannot access each others.  If the data in the local storage is changing and must be shared, you need to rethink the application design.

Local Storage Alternatives

If you need to read/write data in the cloud in a non-volatile and shared way , take advantage of Azure's storage options:  blobs, table storage, queues and SQL Azure databases.  My co-worker Tim Star (Microsoft MVP) has described them in his blog post here.  This may require some application re-architecting, but in the end, your application will run better, stronger, faster in the Azure cloud.


Posted by: Jim White
Posted on: 4/25/2010 at 8:24 PM
Tags: , , , ,
Categories: Cloud Computing | .NET | Web Development
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Visual Studio 2010 Loves the GAC

One of the more frustrating aspects of working with shared assemblies, was Visual Studio's refusal to allow you to directly reference them via the Browse tab of the Add Reference dialog box.  Sure, you *could* navigate to C:\Windows\Assembly and see a nifty icon which represents the library you wish to reference, but no matter how hard you try, VS would not allow you to select it for use in your application.

This required developers to have two stacks of libraries, one for referencing and one for runtime use (in other words, in the GAC). 

To make matters more annoying, other IDEs, such as SharpDevelop (www.sharpdevlop.com) do allow you to navigate to the GAC, and reference a library as expected. 

Thankfully, Visual Studio 2010 has changed for the better.  When you use the Browse tab of the Add Reference dialog box, you can indeed navigate to C:\Windows\Assembly and see the underlying sub-directory structure!  GAC, GAC_32, GAC_MISL and GAC_64 (if you are running the correct version of Windows) are all realized as "normal" directories, rather than fancy icons which can't be selected. 

Do remember that under the GAC directory, you will need to drill down to the unique (auto created at the time of installation) folder, which always follows the following naming convention:

Major.Minor.Build.Revision__publicKeyToken

Some times the little things DO mean a lot ;-)


Posted by: Andrew Troelsen
Posted on: 4/22/2010 at 3:14 PM
Tags: ,
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Windows Azure Storage Options

In my last post I described how to configure your machine to get started developing Windows Azure applications.  We built a simple web role (web site host) and took a look at what role the development fabric played in developing a Windows Azure application.  As soon as we try to build more than the most basic web application we are going to have to start considering our storage options.  Following is a high level overview of the four main storage options.  More details for each option will follow in separate posts.

Table Services : The table service is designed to store non-relational entity type data, serialized DTOs for example.  Redundancy is built in. The size of each row of data is limited to 1 MB and there are some fairly restrictive rules around what types of data may be stored in the table.  We should consider using the Table Service rather than a relational database to persist our data.  Not everything has to be stored in a relational database.  If you can keep your entity relationships simple, live without the joins and manage the relationships yourself, Table Storage looks to be a more simple, cost effective, and scalable approach.  Consider using table storage instead of a traditional database and there is even an ASP.Net session provider available in the SDK that uses table storage.

Blob Storage : There are two kinds of blob storage.  Block Blobs are designed to store up to 200GB of binary data and are optimized for streaming.  A Page Blob can store up to 1 TB of binary data and is designed for random access.  Like table storage, redundancy is built in.  This storage mechanism is ideal for Streaming videos, waves, images, or working with random access files such as fixed length field flat file

Queue Service : The queue service supports 8 KB XML messages and also has redundancy built in.  We are not going to let the size limitation scare us, the intention is not to allow us to put large binary objects on the queue for processing rather the intent is that the message would contain some sort of instruction and if need be the message can reference some object already in storage via a key (the message just contains a pointer to the object we want the worker role to act upon).  The key with using a Queue is this is not a chatty interface this should be used more as a  fire and forget.  Queue messages should be communicating a task the sender wants performed, not performing some type of query that requires a response.

SQL Azure : For the sake of this post we can say SQL Azure is similar to the Sql Server we know and love and that it is designed to store and mange relational data.


Posted by: Tim Star
Posted on: 4/20/2010 at 5:50 AM
Tags: , , , ,
Categories: .NET | Cloud Computing
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed