Welcome to MSDN Blogs Sign in | Join | Help

TeamConf Schweiz - Call for papers

Nach der überaus erfolgreichen TeamConf 2008 in München wird es noch dieses Jahr eine Schwestern-Veranstaltung die „TeamConf Schweiz“ geben.
Somit bietet sich all denen die Möglichkeit am 1. – 3. Dezember nach Zürich auf die Konferenz zu kommen die an der TeamConf in München nicht teilnehmen konnten.

Ziel der Veranstaltung ist es, den Teilnehmern eine breite Kommunikationsplattform rund um das Thema Microsoft Visual Studio Team System (VSTS) und Microsoft Team Foundation Server (TFS) zu bieten. Hierzu werden in Anwenderberichten renommierte Unternehmen über ihre Erfahrungen mit VSTS und TFS sprechen. In Fachvorträgen werden sowohl lösungsorientierte Szenarien und Best Practices mit VSTS vorgestellt, als auch Methoden des modernen Software Engineerings beleuchtet. Zusätzlich wird in Technologiebeiträgen auf die technischen Details einzelner Funktionsbereiche von VSTS und TFS eingegangen.

Zur Zeit läuft der „Call for Papers“ und wir laden alle Interessenten herzlich ein, sich mit einem Beitrag zu einem der oben genannten Themen zu bewerben, den sie dann im Rahmen eines Vortrages während der Konferenz den Teilnehmern vorstellen, oder mit einer kleineren Gruppe in einem Workshop bearbeiten.

Unter http://www.teamconf.ch/callforpapers/ steht eine .pdf-Version des Call for Papers zum Download zur Verfügung. Einsendeschluss ist der 1. September 2008.

Weitere Informationen zur TeamConf Schweiz finden Sie unter www.teamconf.ch

Posted by kcasada | 1 Comments
Filed under:

Die häufigsten Kundenfragen (Teil 6)

Seit drei Wochen ist Silverlight 2 Beta 2 verfügbar; deshalb fokussiert die heutige „Top Customer Questions“-Ausgabe auf diese neue Version.

1.      Unterstützt VS Express Edition Silverlight 2 Beta 2?


Als Voraussetzung für die Installation des VS Tools für Silverlight benötigt man heute mindestens die VS 2008 Standard Edition. Die VS Express Editionen werden nicht unterstützt. Sobald jedoch das Visual Web Developer 2008 Express SP1 verfügbar ist, werden auch die VS Tools für Silverlight upgedated, und somit auch diese Version unterstützen.

 

2.      Was genau ist gemeint mit „Isolated Storage“? Meine HD?

Nein, eine Remote Web Site wird nie Zugriff auf die Dateien haben, die sich auf Ihrer HD befinden. Was eine Silverlight Anwendung machen kann, ist Informationen innerhalb eines Caches zu speichern, die sich ähnlich wie ein Cookie verhält. Dieser Cache wird dann nur für diese Web Site zur Verfügung stehen und der End-Benutzer kann selber entscheiden ob er dieses Recht zulassen möchte oder nicht. Sobald der Browser geschlossen ist, wird der Cache persistent gemacht und wenn der Benutzer zurück auf der gleichen Web Seite ist, steht der Cache wieder zur Verfügung.

 

3.      Unterstützt Silverlight 2 3D?

3D Unterstützung wird voraussichtlich in zukünftigen Versionen von Silverlight integriert. Wenn Sie heute 3D Unterstützung brauchen, dann müssen Sie WPF benutzen.

 

4.      Eine der schönsten Features innerhalb von Expression Blend 2.5 June Preview ist das neue Visual State Manager Tool. Wird es in Zukunft auch etwas Ähnliches für WPF geben?

VSM Unterstützung für WPF ist noch für dieses Jahr geplant, wird jedoch nicht Teil des .NET Frameworks 3.5 SP1 sein, welches bald verfügbar ist.

5.      Werden Silverlight 1.0 Anwendungen auch noch bei Silverlight 2 Beta 2 unterstüzt?

Ja, Kompatibilität mit alten Silverlight 1.0 Anwendungen ist vorhanden, jedoch nicht mit Silverlight 2 Beta 1 Anwendungen.

 

6.      Ist Firefox Version 3 unterstützt?

Ja, die letzte Version von Firefox ist unterstützt.

 

Posted by kcasada | 0 Comments
Filed under:

Update your site for Internet Explorer 8 …

Consistent with the effort to promote further interoperability across the Web, Microsoft will be releasing Internet Explorer 8 to display content in its most standards compliant way by default (by default, standards mode pages will be displayed in “IE8 Standards” mode). Actually there is nothing strange in this practice because this is the typical browser behavior and therefore Internet Explorer 8 adheres to it.

However, browsing with this default setting may cause content written for previous versions of Internet Explorer to display differently than intended. This is the reason why Microsoft has created an IE8 Readiness Toolkit which targets developers and web designers, and should help them to get their sites ready for IE8. In any case in order to enable content providers to update sites with standards compliant content  at a pace that best suits their needs and at the same time maintain backwards compatibility with Internet Explorer 7, Microsoft also provided a compatibility meta-tag that can be used on a per-page or per-site level. By adding this tag IE8 will display content like in IE7.

As a site developer you can therefore choose to update your site to render in IE7 mode (by simply adding a tag) or you can test your site in IE8 standards mode to verify there are no display issues (typical symptoms of incompatibility with IE8 are misaligned page layout, overlapping of text or images and JavaScript issues or errors). You have the choice! Of course the best advice from my side is to start to test your site as soon as possible with the beta version of IE8 with the goal to make it compatible with IE8’s standard rendering mode.

 

This is a list of useful links you should consider as a developer/designer involved in making your site IE8 standard mode compatible.

 

·         Compatibility Knowledge Base article: http://go.microsoft.com/fwlink/?LinkId=1200241   

·         Internet Explorer 8 main site:  http://www.microsoft.com/ie/ie8

·         Internet Explorer Team Blog:  http://blogs.msdn.com/ie

·         Internet Explorer Developer Center:  http://msdn2.microsoft.com/en-us/ie/default.aspx

·         Internet Explorer 8 Readiness Toolkit (for web designers and developers): http://www.microsoft.com/windows/products/winfamily/ie/ie8/readiness/default.htm  

 

Hope it helps,
Ken

Posted by kcasada | 0 Comments
Filed under: ,

SharePoint: Neue Webcasts für Entwickler

image

In den letzten vier Wochen sind 10 Live-Webcasts zum Thema SharePoint-Entwicklung ausgestrahlt worden. Diese Webcasts sind aufgezeichnet worden und stehen unter den folgenden Links zur Verfügung. Eine Registration (Live ID) ist erforderlich.

Besonders empfehlenswert - auch für erfahrene SharePoint Entwickler - ist sicherlich der Webcast Nummer 3: "Silverlight und SharePoint".

  1. Web Parts - Registration und Download
  2. Data Lists - Registration und Download
  3. Silverlight and SharePoint - Registration und Download
  4. Using Event Handlers - Registration und Download
  5. Page Branding - Registration und Download
  6. Workflow - Registration und Download
  7. Web Services - Registration und Download
  8. Page Navigation - Registration und Download
  9. User Management - Registration und Download
  10. Custom Content Types - Registration und Download

Viel Spass!

Posted by Olaf | 1 Comments

A first look at SQL Server 2008 (part 3 of 3)

In this last part of the “SQL Server 2008 first look” series I will set the focus on the new SQL Server 2008 data types. If you missed the first 2 parts you can find them here: part1 & part2.

Let’s start by a really interesting feature, which is something developers would have been having since a long time. This new feature is known as SPARSE Column. But what are SPARSE columns? When can they be used?

SPARSE column are really useful in all those scenarios where you have to work with semi-structured data. Let’s take as an example a product. A product can have different attributes/properties depending on the type of the product itself. If our product is an mp3 player, the typical attributes are probably “capacity” or “battery duration”. If our product is a pair of pant, then probably you have others attributes like “waist size”, or “length”. Now the problem is how you can model a product entity inside a database. One possible solution would be to have one table for each single product’s typology; another approach would be to create a single table for all types of products. The first approach is probably not really manageable, while with the second one each time we are inserting a record into our big table, there would be a big amount of NULL values for all those columns representing a property that is not part of the specific inserted product. Of course this second approach is not really efficient, because NULL values are also using space.

With the SPARSE columns we can archive the data in a more efficient way. How does that work? A SPARSE column is just a column with the new SPARSE attribute (it’s not a new type!). You can therefore declare all columns, which are specific to a product’s type, with the new SPARSE attribute. The particularity of such a declaration is that NULL values stored inside columns decorated with the SPARSE attribute are not going to use any space. That’s the reason why SPARSE columns allow us to archive data in a more efficient way.

CREATE TABLE Product(

Id              int,
Type            nvarchar(16),
Price           decimal(10),
Capacity        nvarchar(8)     SPARSE,
BatteryDuration nvarchar(8)     SPARSE,
WaistSize       int             SPARSE

)

What’s we still need to solve are all the typical open schema problems. What do I mean with that? Each time you need to add a new product’s typology we need to add a certain number of columns. From a SQL point of view this is absolutely not a problem; you can just execute the following command: ALTER TABLE ADD COLUMN_NAME …. Problems arise at application level; in fact, each time we add a column, we then have to consider and manage this new column inside our application. Of course it is possible to build some kind of dynamic application, but this is not always so easy. How does SQL Server 2008 help us in that area? In SQL Server 2005 the typical approach to manage these “dynamic” properties was to put all these columns inside a single column of type XML. With SQL Server 2008 Microsoft did something very similar and introduced a new attribute, the SPARSE COLUMN_SET attribute, which can be added to the declaration of an XML type’s column. What are the benefits? As you can see from the following sample, by adding this new attribute, you can define SPARSE columns (gaining in storage space) and at the same time retrieve all “dynamic” information (in form of an XML) by querying the column of type XML. What’s interesting is that this column is a calculated column and therefore is not persisted on the database. Of course the same flexibility can be found in case you are inserting information.

-- Create table with sparse properties and column_set

CREATE TABLE Product(

Id                   int,
Type                 nvarchar(16),
Price                decimal(10),
Capacity             nvarchar(8)     SPARSE,
BatteryDuration      nvarchar(8)     SPARSE,
WaistSize            int             SPARSE,
Length               int             SPARSE,
ProductProperties    XML COLUMN_SET  FOR ALL_SPARSE_COLUMNS

)

-- Generic XML access to properties through sparse_column_set
SELECT Id, Type, ProductProperties FROM Products

-- Returns an aggregated XML fragment for all non-null sparse columns
101, Playstation, <Capacity>20 GB</Capacity><BatteryDuration>3x</BatteryDuration>
5001, Pant, <WaistSize>32</WaistSize><Length>32</Length>

-- Insert values
INSERT INTO Product(id, Type, Price, ProductProperties)
VALUES (5003, 'Zune', 200,'<Capacity>40 GB</Capacity><BatteryDuration>12 h</BatteryDuration>')

It’s now time to have a look to some of the new data types have been introduced in SQL Server 2008. The first good news is related to the native support for date and time. There are in fact 2 new data types which allow us to store separately date and time. Think about how you write today queries which contain WHERE conditions on a field of type datetime; you always need to consider that DATETIME values contains also time information and therefore you have to be careful in writing the query, otherwise your selection could also forget some records. With this new available option everything should be really simple to manage.

Here some more information on these new data types:

·         DATE

o   Date onlyLarge date range from 0001-01-01 to 9999-12-31

o   SQL standard type

o   3 bytes fixed storage size

·         TIME(n)

o   Time only

o   Optional user specifiable fractional precision

§  up to 100 nanoseconds (default)

o   Format

§  HH:MI:SS[.nnnnnnn]

o   3 to 5 bytes variable storage size

 

There is also a new DATETIME named DATETIME2, which is a wider DATETIME because of the fact that can store datetime until 100 nanoseconds. DATETIMEOFFSET is another new type which at the end is just a DATETIME2 plus information related to the TimeZone. As you can see from the following additional information the time zone ranges between -14:00 and 14:00. Why are minutes included? Because there are time zone that differ also from just 30 minutes (I also just discovered it quite a couple of years ago when I was for holiday in Australia J):

·         DATETIME2(n)

o   Large date range from 0001-01-01 to 9999-12-31

o   Optional user specifiable fractional precision

§  up to 100 nanoseconds (default)

o   3 to 8 bytes variable storage size

o   Time-zone not aware

 

·         DATETIMEOFFSET(n)

o   Contains date, time and time zone offset

o   Large date range from 0001-01-01 to 9999-12-31

o   Optional user specifiable fractional precision

§  up to 100 nanoseconds (default)

o   Format

§  YYYY-MM-DD HH:MI:SS.[.nnnnnnn][+|-]HH:MI

§  time zone offset ranges from -14:00 to 14:00

o   SQL standard type equivalent

§  TIMESTAMP WITH TIME ZONE

o   3 to 8 bytes variable storage size

Another new and really interesting attribute is the FileStream attribute. Think about an application that stores documents. Today to do that you can either create a BLOB field and store your document in binary format or create a simple VARCHAR field and save just the path to the file. The advantage of the first solution is that when you do the backup of your database you are also doing the backup of your documents. Things are a little bit more complicated if you need to access those documents inside your application (you are working with binary values and you don’t have a simple path to files). The ideal solution should be something that takes the best of both mentioned today solutions. The Filestream attribute does exactly that: by applying this attribute to a VARBINARY field, data or better files are not stored in SQL but on the file system. What does it mean? That you don’t have the typical limitation of a VARBINARY(MAX) field of 2GB, the only limitation you have is given by your hard disk capacity. Of course when you are using the filestream attribute, in case of backup you are also doing the backup of your files and you also have a bunch of API that helps you a lot to manage files stored in this new way.

Another interesting feature is filtered index, which allow you to define a where condition (of course with some limitation) on an index. Let’s take as example an archive table with millions of records and let’s suppose that this table is just used to generate reports that include information about the last 12 months. Wouldn’t be nice if you could define a filtered index on the datetime field touching only records which are not older than 12 months and therefore not having to create the index to the whole table? Of course yes.

Last feature that I just want to mention is Performance studio, which is an out-of-the box solution to collect and analyze performance information of all SQL Server instances in a kind of mini datawarehouse.

We are now to the end of this 3 part blog post. I hope I gave you an idea of what is included in the new SQL Server 2008. Of course there is much more, like the new spatial data types or the new HierarchyID data type. So, if you need more information or you just want to go deeper, then navigate to the following SQL server portal http://www.microsoft.com/sql/2008.

Hope it helps,

Ken

Posted by kcasada | 1 Comments
Filed under:

Be the first to know ... download our Event Gadget

During the year the Swiss MSDN Team organizes a series of technical events. Considering that there are a limited number of available places sometimes we cannot accept all registrations.

 

So, if you are using Vista take a look at the Microsoft Event Gadget that will keep you up-to-date on upcoming events relevant to your choice of region, language and audience group. In this way you will be between the first to know about our upcoming events and therefore you will be able to immediately register yourself and get a place for one of our upcoming events.

How can you install the Gadget?

image

By clicking on the Swiss Events bar section of this page, downloading the SwissMSDNEventsGadget.zip file, replacing its .zip extension with a .gadget one and then double-clicking on it.
If the following dialog should appear, ignore it and click Install.
image

The gadget should now be active inside your Windows Vista Sidebar.

What are you waiting for? Register yourself for our next event J

Posted by kcasada | 0 Comments

Support für die Parallelprogrammierung für das .NET FW 3.5 (Community Technology Preview (CTP))

Im Juni ist ein neuer CTP von den "Microsoft Parallel Extensions to .NET Framework 3.5" erschienen. Voraussetzung für diesen CTP ist das .NET Framework 3.5. Den Download finden Sie hier.


Um was geht es hier?

Multicore-Prozessor Maschinen werden zum Standard. Bereits handelsübliche Laptops werden heute mit einem Dual-Core-Prozessor ausgeliefert. Damit aber Programme effektiv auch schneller werden, müssen sie explizit für Multicore-Prozessoren geschrieben werden. Herkömmliche Software wird meist nur auf einem Prozessor ausgeführt und läuft daher auf Multicore-Prozessor Maschinen nicht merklich schneller.

Parallel Computing ist jedoch komplex - Routinen gleichzeitig auf mehreren Prozessoren ausführen zu lassen, ist mit einigen Herausforderungen verbunden, welche von der Multithreading Programmierung her dem einen oder anderen Programmierer bekannt sind (z.B. Locks).

Der erwähnte CTP, welcher vom Microsoft .NET Team in Zusammenarbeit mit Microsoft Research entwickelt worden ist, hat zum Ziel, dass paralleles Programmieren für den Entwickler vereinfacht wird. So soll beispielsweise der Code immer gleich aussehen, egal ob er auf einem Single-Core-Prozessor oder einem Multicore-Prozessor ausgeführt wird.

Paralleles Programmieren ist natürlich vor allem bei sehr rechenintensiven Operationen interessant, wie sie beispielsweise in Grafiksoftware vorkommt. Angenommen, wir möchten zwei 5 MB Bilder aufeinanderlegen, sind dazu mindestens 5 Mio. Operationen notwendig. Die paar Sekunden, welche hier der Benutzer unter Umständen auf die Antwort warten muss, können beispielsweise auf einer Duo-Core-Prozessor Maschine potentiell halbiert werden.


Beispiel

Genau ein solches Beispielprogramm inkl. Quellcode ist Teil des CTPs:

image

Die ersten zwei Bilder wählt der Benutzer aus, das dritte ist eine Kombination aus den ersten zwei und ist mit einem gewissen Rechenaufwand verbunden. Das Test zeigt, dass auf meiner Dual-Core Prozessor Maschine im Parallelmodus die Berechnung 1.57 mal schneller ist!

Wie sieht nun der Code für die Parallelprogrammierung aus?

Für den sequentiellen Modus wird folgender Code verwendet:

image

Es gibt also zwei Schleifen, die äussere iteriert über die y-Achse (j), die innere über die x-Achse (i). Alle (Pixel-)Operationen sind unabhängig voneinander, ein Parallelisieren ist also relativ einfach möglich. Sinnvoll ist beispielsweise eine Parallelisierung pro Zeile (j-Schleife). Sofern also beispielsweise zwei Prozessoren vorhanden wären, könnte sich der erste um die Zeilen 1,3,5... kümmern, der andere um die Zeilen 2,4,6,... Diese Aufgabe kann natürlich klassisch mit Hilfe von System.Threading und zwei Threads gelöst werden.

Mit Hilfe des CTPs und den neuen Klassen, welche als Teil von System.Threading ausgeliefert werden, kann die Parallelisierung dieses Algorithmus' wie folgt programmiert werden:

image

Auf den ersten Blick ist der Code identisch, mit der Ausnahme in der Zeile 1:

Parallel.For(0, height, delegate(j)
  body
);

Parallel ist dabei nichts anderes als eine neue Klasse und bietet beispielsweise die Methode For() an. Sie stellt sicher, dass der body, welcher height Mal ausgeführt werden muss, nach Möglichkeit parallel ausgeführt wird.


Parallel LINQ

Erwähnenswert in diesem Zusammenhang ist sicherlich auch, dass LINQ-to-Objects und LINQ-to-XML sehr gute Ausgangslagen bilden, um von parallel programming zu profitieren: Parallel LINQ (PLINQ) ist nämlich auch Teil des CTPs und ermöglicht, dass LINQ queries parallel ausgeführt werden.

Beispiel:

Angenommen, wir möchten in einem Integer Array jeden Wert um 2 erhöhen, kann dies mittels LINQ-to-Objects wie folgt gelöst werden:

iArr = (from x in iArr select x + 2).ToArray();

Mit PLINQ muss das Query wie folgt angepasst werden:

iArr = (from x in iArr.AsParallel() select x + 2).ToArray();


Einschränkungen dieses CTPs

"This CTP is for testing purposes only. Features and functionality may change before final release, and Microsoft may choose not to provide a final release."


Weitere Infos

Die zentrale Parallel Computing Site von MSDN finden Sie hier: http://msdn.microsoft.com/en-us/concurrency

Posted by Olaf | 0 Comments

A first look at SQL Server 2008 (part 2 of 3)

In the first of this 3 part blog series I mentioned some of the improvements for a better manageability of a SQL Server environment: the Configuration Servers feature, the Resource Governor extensibility and the Auditing out-of-box solution. If you missed it you can find it here. This last feature can be also classified as a DataTracking technology and give me the opportunity to mention another new interesting data tracking technology: the SQL Server 2008 Change Data Capture technology, which allows us to catch information related to changes/operations occurred on our database: DML commands (INSERT, UPDATE and DELETE) and some information related to ALTER TABLE operations.

What does it mean? That if you execute for instance an UPDATE statement on a table and you configure SQL Server to track changes occurring on this specific table (using the out-of-the-box Change Data Capture functionality), you will get an image of the state of the updated record before and after the occurrence of the operation. Extra information like which column has been updated or what’s the name of the operation (update, insert, delete) are also part of this image.

One important thing to say is that Change Data Capture is an asynchronous technology. In fact changes are available just after a couple of seconds after the commit has occurred. In any case everything is transactional because all information needed to create tracking data is taken from the transaction log and therefore as you know, everything you read from the transaction log has already been committed.

It’s now time to see the TSQL enhancements:

·         First, the SQL-Query Editor has intellisense support (if you don’t like it you can disable it). Inside the Query Editor there is also a new error list window that catches all errors, while you are editing TSQL statements.

·        Assignment operators (+=, -=, *=, /=, %=) are now supported

·        Something that I was waiting for (since a long time), is the possibility you now have to declare and immediately assign a value to a variable in just 1 statement:

DECLARE @TODAYDATE DATETIME = GETDATE()

·        There is a new syntax for the VALUES clause, which allows you inserting multiple rows as an atomic operation. Now you can do something like this:

INSERT INTO dbo.publishers (pub_id, pub_name) VALUES (1, 'pub1'),(2, 'pub2'),(3, 'pub3')

 

You can also generate inline table expression in a simpler way:

SELECT * FROM (

VALUES

               (1, 'pub1', 'address1'),

               (2, 'pub2', 'address2'),

               (3, 'pub3', 'address3'),

               (4, 'pub4', 'address4')

)AS (pub_id, pub_name, pub_address)

No more UNION ALL needed J !

·        A new parameter type, the table value parameter (TVP) has been introduced. What does it mean? That you can create a SP and have parameters of type table. Which are the advantages? Think about what you do today if you have a client application that wants to send more data to a Stored Procedure. You can of course call the SP once for each element, or you can for instance open the connection within the client application, create a temporary table (#table), call the SP on the server and then access the temp table on the SP side and start to proceed all table’s records. Another approach, starting from SQL Server 2005, was to pass all parameters as an XML type to a SP. The problem with this solution was that once you are inside the SP, you need to parse the xml in order to extract the parameters.

Today with SQL Server 2008 all this is not anymore necessary; because you can pass an entire table as an input parameter to a SP (there is a new READONLY keyword). With this solution you can pass more records in a block and at the same time you also have strongly type check.

 

·        The MERGE statement has also been introduced; it’s a kind of UPSERT statement with the difference that it is also able to do DELETE operations. With the MERGE statement you can therefore execute an atomic operation which contains logic for UPDATE, INSERT and DELETE operations. Instead of describing the command syntax (which is available in the SQL Server Online Documentation), I can maybe mention a couple of scenarios where the MERGE statement can be really useful. Imagine importing data in a datawarehouse or in general each time you want to synchronize a destination table with a source of data. As an example think about taking a file coming from a Mainframe, loading it in a table and validating all the data. As next step you could use a MERGE statement which could define the following rules: if the record doesn’t exist in the destination table, then an INSERT statement is needed, if it does, then you need an UPDATE, if it exists on the destination table but it doesn’t on the source table, then you need a DELETE.

 

·         With the INSERT command you now have the ability to consume results over DML and what’s more interesting, you can filter the results. With this new feature you can for instance do a DELETE operation using the Output directive, which returns a result-set containing the deleted records and then use this result set (optionally applying a filter) as input for the INSERT statement.

This is the end of the second part. The focus of the third part, which I will publish next week, will be on the SQL Server 2008 new Data Types.

If you are interested in SQL Server 2008 and you want to get a deeper understanding of this new version, then come here in Wallisellen to our free “SQL Server 2008 for Developers (German)” TechTalk the coming 24th of June. Information and registration are available here.

Posted by kcasada | 2 Comments
Filed under:

Composable LINQ to SQL query with dynamic OrderBy

It is a pretty common need to be able to compose a query with multiple "where" parameters at runtime.

There are are scenarios where you want to pass multiple unrelated parameters for your selection that user will chose only at runtime.

Lets take an example.
In our HOL for Silverlight http://blogs.msdn.com/swiss_dpe_team/archive/2008/04/17/silverlight-2-beta-1-end-to-end-hands-on-lab.aspx we have the functionality to search for used Cars by multiple criteria like kilometers, price, model, etc...
Here the search UI:

slchallenge

Normally in LINQ you will write a query like this:

var query = from ad in carfinderDB.ExpandedAds
            where ad.Name.StartsWith("P") && ad.Price <= 10000
            orderby ad.Price
            select ad;

But view that we need to pass any parameters independently or combined (e.g. Kilometers and Price) in the HOL we chose a "bad approach" to use Dynamic SQL to query the DB.
Although it works, it exposes the Web Service to SQL injection attack and we loose all the cool intellisense that LINQ give us. 

Here you can see the "bad" implementation:

public List<ExpandedAd> GetExpandedAds(string sqlQuery)
{
    var ads = carfinderDB.ExecuteQuery<ExpandedAd>(sqlQuery);
    return ads.ToList<ExpandedAd>();

}

Now what about doing it right with LINQ to SQL.

The first help here comes from the capability of LINQ to do query composition and deferred execution. So for the Where clause is very trivial:

var query = from ad in carfinderDB.ExpandedAds
            select ad;

if (!string.IsNullOrEmpty(name)) query = query.Where(ad => ad.Name.StartsWith(name));

if (!string.IsNullOrEmpty(carModelName)) query = query.Where(ad => ad.Name.StartsWith(carModelName));

if (minPrice !=null) query = query.Where(ad => ad.Price >= (minPrice));

if (maxPrice != null) query = query.Where(ad => ad.Price <= (maxPrice));

if (firstRegistration != null) query = query.Where(ad => ad.FirstRegistration >= firstRegistration);

string command = carfinderDB.GetCommand(query).CommandText;

// query is composed and executed at this point
return query.ToList();

In fact you can continue to add new where statements until you execute the query. This is the SQL command that will be sent to SQL Server:

SELECT [t0].[AdID], [t0].[FirstRegistration], [t0].[Kilometers], [t0].[Price], [t0].[ExteriorColor], [t0].[AdType], [t0].[HasNavigationSystem], [t0].[HasAirconditioning], [t0].[HasCruiseControl], [t0].[Description], [t0].[Remarks], [t0].[CarMakeID], [t0].[Name], [t0].[CarModelID], [t0].[CarModelName], [t0].[Doors], [t0].[Seats], [t0].[OriginalPrice], [t0].[DriveTrain], [t0].[FuelType], [t0].[Transmission], [t0].[Cylinders], [t0].[HorsePower], [t0].[VendorID], [t0].[VendorName], [t0].[VendorType], [t0].[Address], [t0].[ZipCode], [t0].[City], [t0].[GeoPosLat], [t0].[GeoPosLng], [t0].[GeoPosQuality], [t0].[PictureID], [t0].[Size], [t0].[ContentType]
FROM [dbo].[ExpandedAd] AS [t0]
WHERE ([t0].[FirstRegistration] >= @p0) AND (([t0].[Price]) <= @p1) AND (([t0].[Price]) >= @p2) AND ([t0].[Name] LIKE @p3)

The challenging part is the dynamic OrderBy. I would love to be able to write something like this query.OrderBy("Price", Desc). For doing this with LINQ you need to write your own OrderBy in form of Extension Method. Here how you can implement it:

public static class DynamicOrderBy
{

           public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty,
                         bool desc) where TEntity : class
           {

               string command = desc ? "OrderByDescending" : "OrderBy";

               var type = typeof(TEntity);

               var property = type.GetProperty(orderByProperty);

               var parameter = Expression.Parameter(type, "p");

               var propertyAccess = Expression.MakeMemberAccess(parameter, property);

               var orderByExpression = Expression.Lambda(propertyAccess, parameter);

               var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },

                                      source.Expression, Expression.Quote(orderByExpression));

               return source.Provider.CreateQuery<TEntity>(resultExpression);

           }

}

Now you can simply use it this way:

query = query.OrderBy("Price", false);

you can even use it with multiple columns:

query = query.OrderBy("Price", false).OrderBy("Name", true);

Here the final service implementation with multi parameters, dynamic orderby and paging:

       //service call from the client
       GetExpandedAds("P",null,1000,100000,new DateTime(2000,1,1),"Price",true,0,10);

       public List<ExpandedAd> GetExpandedAds(string name, string carModelName, int? minPrice, int? maxPrice,
              DateTime firstRegistration, string orderByColumName, bool orderDescending, int skip, int take)
       {
           using (ComparisCarfinderDBDataContext carfinderDB = new ComparisCarfinderDBDataContext())
           {
               var query = from ad in carfinderDB.ExpandedAds
                           select ad;

               if (!string.IsNullOrEmpty(name)) query = query.Where(ad => ad.Name.StartsWith(name));
               if (!string.IsNullOrEmpty(carModelName)) query = query.Where(ad => ad.Name.StartsWith(carModelName));
               if (minPrice !=null) query = query.Where(ad => ad.Price >= (minPrice));
               if (maxPrice != null) query = query.Where(ad => ad.Price <= (maxPrice));
               if (firstRegistration != null) query = query.Where(ad => ad.FirstRegistration >= firstRegistration);
               if (!string.IsNullOrEmpty(orderByColumName)) query = query.OrderBy(orderByColumName, orderDescending);

               //code to anylize the SQL statement
               string command = carfinderDB.GetCommand(query).CommandText;

               return query.Skip(skip).Take(take).ToList();
           }  
       }

That will generate this SQL statement:

SELECT [t0].[AdID], [t0].[FirstRegistration], [t0].[Kilometers], [t0].[Price], [t0].[ExteriorColor], [t0].[AdType], [t0].[HasNavigationSystem], [t0].[HasAirconditioning], [t0].[HasCruiseControl], [t0].[Description], [t0].[Remarks], [t0].[CarMakeID], [t0].[Name], [t0].[CarModelID], [t0].[CarModelName], [t0].[Doors], [t0].[Seats], [t0].[OriginalPrice], [t0].[DriveTrain], [t0].[FuelType], [t0].[Transmission], [t0].[Cylinders], [t0].[HorsePower], [t0].[VendorID], [t0].[VendorName], [t0].[VendorType], [t0].[Address], [t0].[ZipCode], [t0].[City], [t0].[GeoPosLat], [t0].[GeoPosLng], [t0].[GeoPosQuality], [t0].[PictureID], [t0].[Size], [t0].[ContentType]
FROM [dbo].[ExpandedAd] AS [t0]
WHERE ([t0].[FirstRegistration] >= @p0) AND (([t0].[Price]) <= @p1) AND (([t0].[Price]) >= @p2) AND ([t0].[Name] LIKE @p3)
ORDER BY [t0].[Price] DESC

Much cleaner than the dynamic SQL approach and easy to use with no risk of SQL Injection attacks

Ciao

Ronnie Saurenmann

Posted by ronnies | 0 Comments

A first look at SQL Server 2008 (part 1 of 3)

During the last days I found the time to have a first look at SQL Server 2008. In this 3 parts blog (I’ll post the second one the coming week) I will summarize some of the most interesting features I discovered during my tour inside this new version of our popular database.

To start let me mention some of the new technologies that allow a better manageability of a SQL Server environment and therefore improve the life of developers and database administrators. In fact, today we are struggling more and more in quite complex environments; the product itself, SQL Server, has become more complex. So to help us working in such a complexity, SQL Server 2008 is coming with plenty of new interesting features.

One of these is the ability to designate a SQL Server instance as a configuration server (the feature is known as Configuration Server), and then bind it to a group of servers. The idea is that you can apply things or do things to the whole group of servers via the configuration server. It is for instance possible to execute a TSQL statement on all servers and obtain as a result the union of all the single servers result sets. Another interesting thing you can do is to apply policies to the configuration server (using the new Declarative Management Framework) and therefore having them applied automatically to all “child” servers. But, what are these policies? An example of policy could be a rule that defines that there must be a backup for each database that is not older than 2 days; another could define that the name of all created views must have “vw_” as root.

One thing to know is that all these policies can be organized into groups and that SQL Server 2008 is coming with some out-of the-box policy groups; one of these groups contains a set of rules which are considered to be best practice (if I remember the group is labeled “BestPractise”). So, instead of assigning each single policy to an object, you can easily work with groups.

But, how can you manage all these policies? As I said, policies can be organized into groups. Moreover, SQL Server 2008 is coming with the new SQL Server Management Studio, which also brings an improved UI. With this new UI you can monitor all objects inside a database and therefore be warned in case of policy violation. Of course the monitoring activity can be configured in different ways: you can avoid the violation of policies by preventing users to smash a defined rule or, on a regular basis, you can simply do a manual check to verify if your database conforms to specific policies. There is also another option, which gives you the opportunity to automate everything in a way so that you will be notified in case of rule violation.

Another interesting feature is the Resource Governor, which is an extension of the SQL Server 2008 engine, which allows you to solve problems like the runaway queries: somebody connects to the database, write a query in a wrong way (for instance forgetting a join condition), the query getting executed consumes all available resources and then the result is that we have our database server completely down. Thanks to the Resource Governor you can define resource groups, which are logical groups which identify a specific set of activities. You can for instance define a logic group that includes all backup activities and another group that includes all reporting activities and then assign each single group to a resource pool group, which defines how resources have to be used. You can for example configure the resource pool not to consume more than 40% CPU and more than 30% memory and so on. In simple words the Resource Governor can be seen as the arbitrator of resources.

Something that is more tied to the security aspects, are the improved Auditing functionalities: a solution that can be used to trace a wide range of activities occurring on a database server, including TSQL commands, and therefore more interesting, including SELECT statements with filtering support. This is really a nice feature, because in the past, in order to capture a select statement, you had to start and work with the SQL Server Profiler, which was also the case for tracing permission operations. So now, the full support has been completely integrated inside SQL Server 2008 and available as an out-of-the box solution with reporting capabilities.

This is the end of the first part. In the second part we will have a look to some of the new nice TSQL-enhancements. So Stay tuned!

Ken

Posted by kcasada | 1 Comments
Filed under: