Pages

Monday, August 30, 2010

Working with untyped datasets

Example : Working with untyped datasets

DataTable dataTable = new DataTable();
using (var connection = new SqlConnection
(Settings.Default.SkeetySoftDefectsConnectionString))
{
string sql = "SELECT Summary, Status FROM Defect";
new SqlDataAdapter(sql, connection).Fill(dataTable);
}
var query = from defect in dataTable.AsEnumerable()
where defect.Field("Status") != Status.Closed
select defect.Field("Summary");
foreach (string summary in query)
{
Console.WriteLine (summary);
}



Untyped datasets have two problems as far as LINQ is concerned. First, we don’t have
access to the fields within the tables as typed properties; second, the tables themselves
aren’t enumerable. To some extent both are merely a matter of convenience—we
could use direct casts in all the queries, handle DBNull explicitly and so forth, as well as
enumerate the rows in a table using dataTable.Rows.Cast. These
workarounds are quite ugly, which is why the DataTableExtensions and DataRow-
Extensions classes exist.
Code using untyped datasets is never going to be pretty, but using LINQ is far nicer
than filtering and sorting using DataTable.Select. No more escaping, worrying
about date and time formatting, and similar nastiness.
Listing 12.10 gives a simple example. It just fills a single defect table and prints the
summaries of all the defects that don’t have a status of “closed.”

Saturday, August 28, 2010

Linked Lists

If you’ve ever had to visit a hospital emergency room, you’ll know that waiting in a
queue is one of the defining features of the experience unless you were either very lucky
or very unlucky. If you were lucky, the queue will have been empty and you will not
have had to wait. Alternatively, if you were unlucky, your condition may have been
sufficiently perilous that you got to jump to the head of the queue.
In medical emergencies, a triage system will be in place to work out where each arriving
patient should go in the queue. A similar pattern crops up in other scenarios—frequent
fliers with gold cards may be allocated standby seats at the last minute even though
others have been waiting for hours; celebrities might be able to walk right into a res-
taurant for which the rest of us have to book a table weeks in advance.
The LinkList class is able to model these sorts of scenarios. At its simplest, you
could use it like a Queue—call AddLast to add an item to the back of the queue (as
Enqueue would), and RemoveFirst to take the item off the head of the queue (like
Dequeue would). But you can also add an item to the front of the queue with
AddFirst. Or you can add items anywhere you like in the queue with the AddBefore and
AddAfter methods. Example 9-13 uses this to place new patients into the queue.

Example 9-13. Triage in action
private LinkedList waitingPatients = new LinkedList();
...
LinkedListNode current = waitingPatients.First;
312 | Chapter 9: Collection Classeswhile (current != null)
{
if (current.Value.AtImminentRiskOfDeath)
{
current = current.Next;
}
else
{
break;
}
}
if (current == null)
{
waitingPatients.AddLast(newPatient);
}
else
{
waitingPatients.AddBefore(current, newPatient);
}

This code adds the new patient after all those patients in the queue whose lives appear
to be at immediate risk, but ahead of all other patients—the patient is presumably either
quite unwell or a generous hospital benefactor. (Real triage is a little more complex, of
course, but you still insert items into the list in the same way, no matter how you go
about choosing the insertion point.)
Note the use of LinkedListNode—this is how LinkedList presents the queue’s
contents. It allows us not only to see the item in the queue, but also to navigate back
and forth through the queue with the Next and Previous properties.

Dictionaries and LINQ

Because all IDictionary implementations are also enumerable, we can
run LINQ queries against them. Given the RecordCache class in Example 9-5, we might
choose to implement the cache item removal policy as shown in Example 9-10.
Example 9-10. LINQ query with dictionary source
private void DiscardAnyOldCacheEntries()
{
// Calling ToList() on source in order to query a copy
// of the enumeration, to avoid exceptions due to calling
// Remove in the foreach loop that follows.
var staleKeys = from entry in cachedRecords.ToList()
where IsStale(entry.Value)
select entry.Key;
foreach (int staleKey in staleKeys)
{
cachedRecords.Remove(staleKey);
}
}

But it’s also possible to create new dictionaries with LINQ queries. Example 9-11 il-
lustrates how to use the standard ToDictionary LINQ operator.
Example 9-11. LINQ’s ToDictionary operator
IDictionary buildingIdToNameMap =
MyDataSource.Buildings.ToDictionary(
building => building.ID,
building => building.Name);

This example presumes that MyDataSource is some data source class that provides a
queryable collection containing a list of buildings. Since this information would typi-
cally be stored in a database, you would probably use a database LINQ provider such
as LINQ to Entities or LINQ to SQL. The nature of the source doesn’t greatly matter,
though—the mechanism for extracting the resources into a dictionary object are the
same in any case. The ToDictionary operator needs to be told how to extract the key
from each item in the sequence. Here we’ve provided a lambda expression that retrieves
the ID property—again, this property would probably be generated by a database map-
ping tool such as the ones provided by the Entity Framework or LINQ to SQL. (We
will be looking at data access technologies in a later chapter.) This example supplies a
second lambda, which chooses the value—here we pick the Name property. This second
lambda is optional—if you don’t provide it, ToDictionary will just use the entire source
item from the stream as the value—so in this example, leaving out the second lambda
would cause ToDictionary to return an IDictionary (where Building is
whatever type of object MyDataSource.Buildings provides).
The code in Example 9-11 produces the same result as this:
var buildingIdToNameMap = new Dictionary();
foreach (var building in MyDataSource.Buildings)
{
buildingIdToNameMap.Add(building.ID, building.Name);
}

Wednesday, August 25, 2010

Basic data access with ADO.NET

string sqlConnectionString = @"Data Source=.\sqlexpress;" +
"Initial Catalog=AdventureWorksLT2008;Integrated Security=True";
string state = "California";
using (DbConnection conn = new SqlConnection(sqlConnectionString))
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText =
"SELECT AddressLine1, AddressLine2, City FROM SalesLT.Address WHERE " +
"StateProvince=@state";
DbParameter stateParam = cmd.CreateParameter();
stateParam.ParameterName = "@state";
stateParam.Value = state;
cmd.Parameters.Add(stateParam);
conn.Open();
using (DbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string addressLine1 = reader.GetString(0);
// AddressLine2 is nullable, so we need to be prepared to get
// back either a string or a DBNull
string addressLine2 = reader.GetValue(1) as string;
string city = reader.GetString(2);
Console.WriteLine(addressLine1);
Console.WriteLine(addressLine2);
Console.WriteLine(city);
}
}
}

dynamic Versus var

At first glance, the difference between dynamic and var may not be entirely obvious.
With either, you do not have to tell the compiler explicitly what type of data you’re
working with—the compiler ultimately ensures that the right thing happens. For ex-
ample, whether using dynamic or var, the + operator has the same effect that it would
have if you had used it with explicitly typed variables. So why do we need both?
The difference is timing: var does things much earlier. The C# compiler insists on being
able to work out what type of data is in a var variable at compile time. But with
dynamic, it works it out at runtime. This means there are some things you can do with
dynamic that you cannot do with var. As Example 18-4 showed, you can use dynamic
for the arguments of a function declaration, and also for its return type. But this would
be illegal with var:
static var WillNotCompile(var a, var b) // Error
{
return a + b;
}

The compiler has insufficient information to work out at compile time what the argu-
ment and return types are here. But with dynamic, that doesn’t matter—the compiler
doesn’t need to know at compile type what type of data we’re using because it will
generate code that works out what to do at runtime.
Here’s another thing that dynamic can do that var cannot:
dynamic differentTypes = "Text";
differentTypes = 42;
differentTypes = new object();

The value in differentTypes changed from one line to the next. If we had used var, this
would have been illegal—a var variable’s type is determined by the expression used to
initialize it, so in this case, it would have been a string, meaning the second line would
have failed to compile.
So dynamic and var perfectly represent the distinction between dynamic and static: a
dynamic variable’s type (and consequently the behavior of any operations using that
variable) is determined at runtime; a var variable’s type is static—it is determined at
compile time and cannot change.

Query Expressions Versus Method Calls

LINQ query as method calls

var bigFiles = GetAllFilesInDirectory(@"c:\").
Where(file => new FileInfo(file).Length > 10000000);
Let’s compare this with the components of the original query:
var bigFiles = from file in GetAllFilesInDirectory(@"c:\")
where new FileInfo(file).Length > 10000000
select file;


using where

var bigFiles = from file in GetAllFilesInDirectory(@"c:\")
where new FileInfo(file).Length > 10000000
select "File: " + file;


using select

var bigFiles = GetAllFilesInDirectory(@"c:\").
Where(file => new FileInfo(file).Length > 10000000).
Select(file => "File: " + file);

Sunday, August 22, 2010

Interop with COM and Win32

Example Setting a property on the control

public Form1()
{
InitializeComponent();
string pdf = "http://www.interact-sw.co.uk/downloads/ExamplePdf.pdf";
pdfAxCtl.src = pdf;
}

Saturday, August 21, 2010

The dynamic Type

Example Using dynamic

C# 4.0 introduces a new type called dynamic. In some ways it looks just like any other
type such as int, string, or FileStream: you can use it in variable declarations, or func-
tion arguments and return types, as Example 18-4 shows. (The method reads a little
oddly—it’s a static method in the sense that it does not relate to any particular object
instance. But it’s dynamic in the sense that it uses the dynamic type for its parameters
and return value.)

static dynamic AddAnything(dynamic a, dynamic b)
{
dynamic result = a + b;
Console.WriteLine(result);
return result;
}

Basic data access with ADO.NET


string sqlConnectionString = @"Data Source=.\sqlexpress;" +
"Initial Catalog=AdventureWorksLT2008;Integrated Security=True";
string state = "California";
using (DbConnection conn = new SqlConnection(sqlConnectionString))
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText =
"SELECT AddressLine1, AddressLine2, City FROM SalesLT.Address WHERE " +
"StateProvince=@state";
DbParameter stateParam = cmd.CreateParameter();
stateParam.ParameterName = "@state";
stateParam.Value = state;
cmd.Parameters.Add(stateParam);
conn.Open();
using (DbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string addressLine1 = reader.GetString(0);
// AddressLine2 is nullable, so we need to be prepared to get
// back either a string or a DBNull
string addressLine2 = reader.GetValue(1) as string;
string city = reader.GetString(2);
Console.WriteLine(addressLine1);
Console.WriteLine(addressLine2);
Console.WriteLine(city);
}
}
}]

Friday, August 20, 2010

C# 4.0, .NET 4, and Visual Studio 2010

Since C# favors general-purpose language features designed to be composed with one
another, it often doesn’t make sense to describe individual new features on their own.
So rather than devoting sections or whole chapters to new features, we cover them in
context, integrated appropriately with other, older language features. The section
you’re reading right now is an exception, of course, and the main reason is that we
expect people already familiar with C# 3.0 to browse through this book in bookstores
looking for our coverage of the new features. If that’s you, welcome to the book! If you
look in the Preface you’ll find a guide to what’s where in the book, including a section
just for you, describing where to find material about C# 4.0 features.
That being said, a theme unites the new language features in version 4: they support
dynamic programming, with a particular focus on making certain interoperability sce-
narios simpler. For example, consider the C# 3.0 code in Example 1-3 that uses part
of the Office object model to read the Author property from a Word document.

Example 1-3. The horrors of Office interop before C# 4.0

static void Main(string[] args)
{
var wordApp = new Microsoft.Office.Interop.Word.Application();
object fileName = @"WordFile.docx";
object missing = System.Reflection.Missing.Value;
object readOnly = true;
Microsoft.Office.Interop.Word._Document doc =
wordApp.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing);
object docProperties = doc.BuiltInDocumentProperties;
Type docPropType = docProperties.GetType();
object authorProp = docPropType.InvokeMember("Item",
BindingFlags.Default | BindingFlags.GetProperty,
null, docProperties,
new object[] { "Author" });
Type propType = authorProp.GetType();
string authorName = propType.InvokeMember("Value",
BindingFlags.Default |BindingFlags.GetProperty,
null, authorProp,
new object[] { }).ToString();
object saveChanges = false;
doc.Close(ref saveChanges, ref missing, ref missing);
Console.WriteLine(authorName);
}

That’s some pretty horrible code—it’s hard to see what the example does because the
goal is lost in the details. The reason it is so unpleasant is that Office’s programming
model is designed for dynamic languages that can fill in a lot of the details at runtime.
C# 3.0 wasn’t able to do this, so developers were forced to do all the work by hand

Example 1-4 shows how to do exactly the same job in C# 4.0. This is a lot easier to
follow, because the code contains only the relevant details. It’s easy to see the sequence
of operations—open the document, get its properties, retrieve the Author property’s
value, and close the document. C# 4.0 is now able to fill in all the details for us, thanks
to its new dynamic language feat

Example 1-4. Office interop with C# 4.0


static void Main(string[] args)
{
var wordApp = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word._Document doc =
wordApp.Documents.Open("WordFile.docx", ReadOnly: true);
dynamic docProperties = doc.BuiltInDocumentProperties;
string authorName = docProperties["Author"].Value;
doc.Close(SaveChanges: false);
Console.WriteLine(authorName);
}


This example uses a couple of C# 4.0 features: it uses the new dynamic keyword for
runtime binding to members. It also uses the support for optional arguments. The
Open and Close methods take 16 and 3 arguments, respectively, and as you can see from
Example 1-3, you need to provide all of them in C# 3.0. But Example 1-4 has only
provided values for the arguments it wants to set to something other than the default.
Besides using these two new features, a project containing this code would usually be
built using a third new interop feature called no-PIA. There’s nothing to see in the
preceding example, because when you enable no-PIA in a C# project, you do not need
to modify your code—no-PIA is essentially a deployment feature. In C# 3.0, you had
to install special support libraries called primary interop assemblies (PIAs) on the target
machine to be able to use COM APIs such as Office automation, but in C# 4.0 you no
longer have to do this. You still need these PIAs on your development machine, but the
C# compiler can extract the information your code requires, and copy it into your
application. This saves you from deploying PIAs to the target machine, hence the name,
“no-PIA”.
While these new language features are particularly well suited to COM automation
interop scenarios, they can be used anywhere. (The “no-PIA” feature is narrower, but
it’s really part of the .NET runtime rather than a C# language feature.)