in

mscommunity.net

Interactive mscommunity.net online activities

data.hr

DLinqy-thingy, Part One

At last, I found some spare time to start playing with that Linq2SQL thing. Installed VS2008 RTM. fired it up, created a new C# console project, added a reference to System.Data.Linq, created the appropriate .dbml to Northwind database, and typed in the following code, more or less copied from the ScottGu blog (http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx):

            northwindDataContext db = new northwindDataContext();

            Product product = db.Products.Single(p => p.ProductName == "Flotemysost");
            product.UnitPrice = 99;
            product.UnitsInStock = 5;

            db.SubmitChanges();

 

Fired up the SQL Server profiler to capture what's really happening, and pressed F5.

And here's what was in the profiler trace:

exec sp_executesql N'SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ProductName] = @p0',N'@p0 nvarchar(11)',@p0=N'Flotemysost'

exec sp_executesql N'UPDATE [dbo].[Products]
SET [UnitPrice] = @p9, [UnitsInStock] = @p10
WHERE ([ProductID] = @p0) AND ([ProductName] = @p1) AND ([SupplierID] = @p2) AND ([CategoryID] = @p3) AND ([QuantityPerUnit] = @p4) AND ([UnitPrice] = @p5) AND ([UnitsInStock] = @p6) AND ([UnitsOnOrder] = @p7) AND ([ReorderLevel] = @p8) AND (NOT ([Discontinued] = 1))',
N'@p0 int,@p1 nvarchar(11),@p2 int,@p3 int,@p4 nvarchar(16),@p5 money,@p6 smallint,@p7 smallint,@p8 smallint,@p9 money,@p10 smallint',
@p0=71,@p1=N'Flotemysost',@p2=15,@p3=4,@p4=N'10 - 500 g pkgs.',@p5=$21.5000,@p6=26,@p7=0,@p8=0,@p9=$99.0000,@p10=5


What can we say about the SELECT statement? It's simple, but there are at least two things wrong. First, notice that the SELECT list incudes *all* columns from the Products table, although we had no intention of using them all. I agree, Linq has no way of guessing what we're going to need and what not, but anyway it's way too easy to type in an equivalent of "select *" without being aware of it. Second, the @p0 parameter is nvarchar(11). It's just plain stupid, IMHO. Remember, we have the data model in the project, and the Linq engine knows that the ProductName column's datatype is nvarchar(40). Nevertheless, it decided to simply count the characters from the "Flotemysost" const. Why, oh why? OK, so we will get the different query plan depending on the value passed to the query. Not exactly good for the plan reuse, right?

And what to say about the "optimistic" UPDATE statement? Well, it's just plain wrong.. Please -- never, never, never update the data without using a stored procedure. Please :)

TBC.

Dean

Published vlj 21 2008, 07:06 by dvitner
Filed under:

Comments

 

anonymous said:

Dean, you can modify optimistic concurrency checking. Try reading TFM ;) "Optimistic Concurrency Overview (LINQ to SQL)"

About fetching all fields. Well, this is normal in ORM world because you are working with entities usually, not with their subsets. But you can also delay load (or not load at all <- not supported in LINQ to SQL I think) fields you wish. Or, you can use a projection. But then you can't save the data that easy.

veljača 22, 2008 5:45
 

dvitner said:

Miha, thanks for the comment.

I am aware that the default behaviour of Linq2SQL could be tweaked, and even that stored procedures could be used. However, right now I'm more interested in "out-of-the-box" experience, something I'm afraid is the way this thing will be (mis)used by the vast majority of ordinary users.

And yes, I'm biased :)

veljača 22, 2008 8:30
 

anonymous said:

That sort of users would abuse/and are abusing all sort of things anyway :-).

veljača 22, 2008 9:51
Powered by Community Server (Commercial Edition), by Telligent Systems