Category Archives: Data Access

A few of the many syntax changes in VB (and Linq for SQL queries)

VB9 has come a long way in the new March CTP of Orcas! Paul Vick has a quick list of what is now in there. And there are a lot of good details in the msdn documentaiton that comes along with the CTP.

A few things I noticed quickly when bringing my LINQ for SQL demos over to the new bits.

  • First, and happily, the named parameter syntax of := is no longer necessary. You can just type =, like a normal person.
  • You need to be explicit about using the reference to the entity when refering to properties. In other words where I could say
     From s In db.Suppliers_
                Where CompanyName = “Exotic Liquids” …
    I now need to put  “s.” in front of the CompanyName property
  • The anonymous types have been fleshed out more and you need to use the With keyword when creating one.
  • Also in the anonymous types, when you are definining a new named parameter, you need the “.” in front of that parameter, so it is obviously a property of the anonymous type.
  • Maybe this isn’t the ultimate way to do it, but it seems that if you want to further leverage one of the properties of that anonymous type, eg to order on, then you need to name the anonymous type and reference it in the order by clause. Again, maybe this isn’t THE way, but it’s the way I got my code working again.

Here’s a before (as in earlier CTP) and an after (March CTP) example of a simple query that does all of these things.

OLD
From s In db.Suppliers _
            Select New {Company := CompanyName, Country, Products}

NEW
From s In db.Suppliers _
            Select New With {.Company = s.CompanyName, s.Country, s.Products}

Here’s what it looks like with a nested query
  From s In db.Suppliers _
            Select New With {.Company = s.CompanyName, s.Country, _
            .Products = (From p In s.Products _
                Select New With {p.ProductName})}

OLD with Order By
From s In db.Suppliers _
            Select New {s.CompanyName, s.Country, s.Products} _
            Order By CompanyName

NEW with Order By
  Dim mylist = From s In db.Suppliers _
            Select s2 = New With {s.CompanyName, s.Country, s.Products} _
            Order By s2.CompanyName

I’ve seen samples where “s” has been used for both the reference to the items in the db.suppliers collection AND to the name of the new anonymous type. That scares me, so I used a new variable (s2).

There is also a whole new set of query samples in the MSDN documentation.

Ooh goody another post on the adonet team blog

The ADO NET Team has been cranking out fab content on their blog. Brian Dawson just wrote a post all about Object Services.

In trying to sort out all of the options that we now have with Entity Framework and LINQ, I’m always happy to see a list like this. But go read the whole post so nothing is out of context

What can you do with Object Services?

Here’s a bullet list of some of the normal operations which object services can provide:

·         Query using LINQ or Entity SQL

·         CRUD

·         State Management – change tracking with events

·         Lazy loading

·         Inheritance

·         Navigating relationships

More features of Object Services allow for data conflicts resolution. For example, Object Services supports:

·         Optimistic concurrency

·         Identity resolution –  keeping on copy of the object even from several different queries

·         Merging

·         Refreshing data with overwrite options (ie: server wins or client wins)

EDMGEN.exe – EDM Command Line Gen Tool

I saw mention of this new version of the command line tool in this forum post so I went looking in the MarchCTP. I modified some of the desciriptions a little to fit them onto a powerpoint slide, so this is a tad different than the real tihng

C:\WINDOWS\Microsoft.NET\Framework\v3.5.20209>edmgen /help


Microsoft (R) EdmGen version 2.0.0.0
Copyright (C) Microsoft Corporation 2006. All rights reserved.

                                           EdmGen Options
/mode:ValidateArtifacts                 Validate the ssdl, msl, and csdl files
/mode:FullGeneration                    Generate ssdl, msl, csdl, and objects from the database
/mode:FromSsdlGeneration                Generate msl, csdl, and objects from an ssdl file
/mode:EntityClassGeneration             Generate objects from a csdl file
/mode:ViewGeneration                    Generate mapping views from ssdl, msl, and csdl files
/project:<string>                       The base name to be used for all the artifact files (short form: /p)

/connectionstring:<connection string>   The connection string to the database that you would like to connect to (short form: /c)
/incsdl:<file>                          The file to read the conceptual model from
/inmsl:<file>                           The file to read the mapping from
/inssdl:<file>                          The file to read the storage model from
/outcsdl:<file>                         The file to write the generated conceptual model to
/outmsl:<file>                          The file to write the generated mapping to
/outssdl:<file>                         The file to write the generated storage model to
/outobjectlayer:<file>                  The file to write the generated object layer to
/outviews:<file>                        The file to write the pre generated view objects to
/language:Vb                            Generate code using the VB language
/language:CSharp                        Generate code using the C# language
/namespace:<string>                     The namespace name to use for the conceptual modely types
/entitycontainer:<string>               The name to use for the EntityContainer in the conceptual model
/help                                   Display the usage message (short form: /?)
/nologo                                 Suppress copyright message

 

Feb CTP of Orcas with LINQ and more coming soon

Since a few people have asked me in email (which is not a problem…), I thought I’d make mention that the next CTP for Orcas is the February CTP. It is coming out either late February or early March. This version, though still a CTP, should have all of the LINQ and EF stuff updated and incorporated, including the UI stuff such as the designer and the templates that we currently have to go back to the May CTP for, as well as some major enhancements to LINQ in VB, a LinqDataSource for databinding in web apps and more.

The shadowy side of LINQ to SQL

Don’t get me wrong. I love LINQ and LINQ for SQL. But the more I have been digging into it the more things I discover that, as a developer, I may want to explicitly choose how to use. That’s probably why my talk on Linq for SQL with Web Apps last night at VTdotNET was pretty long. (Going to have to cut it down to fit a one hour slot at DevConnections – egad!)

I spent a lot of time trying to be sure people were aware of what is going on in the background when they may just see on the surface that they are so easily writing a query and the data so easily appears the way they want it to.

1) For example, the default Optimistic Concurrency. Not that Optimistic Concurrency is always a bad thing, but almost everyone groaned when I said that it was on by default – for all columns. The UpdateCheck property of LINQ to SQL column (oh, it’s so much easier to say and type “DLINQ”) defaults at Always. When you use the designer, that’s what you get. The enum I prefer is “WhenChanged“. The current (May CTP) designer doesn’t have a property exposed at the UI, which means that if you want to change it in code, you can’t use the UI again or it will be overwritten. Of course, this is the May CTP and all of this might change in future CTPs, Betas or the release. When writing any of your own update logic, it’s a lot of work to deal with all of those columns. I suppose any way you slice it, dealing with concurrency is a pain in the butt and what LINQ for SQL has is a stake in the ground.

2) Another biggie is to have an awareness of how the LINQ queries are turned into TSQL which is really matter of knowing is the hard work done in TSQL or in memory after the data is returned? I’ve been talking with Frans Bouma (creator of LLBLGen who knows a lot about ORM) about this as I was trying to understand what I was seeing. There doesn’t seem to be a discernible pattern – though there must be and I’m just not seeing it (until maybe I explore 2 or 3000 more queries? :-)) For the most part, the queries I looked at in SQL Profiler looked as I would expect them. And certainly much smarter people than myself are creating the algorithms to do this work. But there was one query that stood out like a sore thumb.

The query gets data from one table which has child objects. I’m displaying data from the child objects, so I do expect lazy loading to first grab the parent data and then grabs a set of child objects for each parent. It also does some filtering based on the child table. For example suppliers and it’s products.

from s in db.suppliers where s.Products.Count > 2 select s

So on the surface, I’m just asking for this sql query.

select * from suppliers  WHERE ((
    SELECT COUNT(*)
    FROM [Products] WHERE products.[SupplierID] = suppliers.[SupplierID])) >2

This returns 16 of the 29 suppliers in Northwind.

And then as I populate my data control and ask for product info, I expect lazy loading to go out and get the products for each of the 16. So 16 more queries.

But what I get is two additional queries for each supplier.

First there is a query which gets the count of products for the supplier. Second is a query that gets the products.

I can’t figure out why the first query is necessary.

Of course, (caveat caveat caveat), I can’t imagine being the person (probably more than one! ) that is creating the code that has to take any weird LINQ query I come up with and translate it into TSQL. So my point is more that [some] developers might want to know that this is going on and make a decision about whether or not to use the defaults, override them (note this from the Dec 12th chat with the LINQ folks about upcoming mods: You can disable deferred loading by setting a property on the DataContext, and then you can describe pre-fetch behavior using the new DataShape class.“) or just write your own data access.

3) Which begs to point out Lazy Loading: Again there are pros and cons to any technology choice you make. Just know that it’s going on and how it changes based on how you do write or enumerate your queries. The samples of lazy loading usually show code which explicitly enumerates through query results. What people also need to think about is that it’s happening elsewhere too. For example, the way I defined the datalist that displays the above Supplier/Product data forces lazy loading to happen.

4) Caching and nullables. I’m putting these together because I haven’t dug into them. I think anyone interested in performance should know how LINQ caches data and what to expect from it (and what NOT to expect from it).

5) All those other table/column properties. I haven’t gotten to them yet. For example, DeleteCommand on a Table. I wonder if that just lets me point to the stored proc that I want to be run for a delete.

6) When you think you found a way to do something, there are probably 18 other ways to do it too. Of course, that’s nothing new! 🙂

I have a lot more banging around in my head. But I gotta get back to work. Though I still need to work up a good response to the guy who summed up LINQ to SQL as a “glorified dataset”.

Though I was worried that I was a little fanatical when I presented this stuff last night (hey, it’s data access, whadya want?), I was happy to hear from attendees that they were really glad I went behind the magic to show what’s happening in the background that might be of interest to them.