Home MVC Storefront

LinqToSql: Momma Said Knock You Out

Why don't you rip with me, the maniac psycho Cuz when I pull out my jammy, get ready cuz it might go Blauh!
In my last post on LinqToSql, I covered the DataContext and likened it to the Great Gazoo and Phoebe Cates - possibly the worst analogies in any form of tech writing, ever. But that's what you've come to expect so I won't disappoint. This aint no Peanut Butter Jelly Time or Hamster Dance ya know... In this post I'm going to take it a step further and show you how you can polish the chrome on LinqToSql so that you can cleanly separate your What from your How. I'm also going to go a little bit into how SubSonic fits into the whole "LINQ thang". Don't call it a comeback For the last week I've been beating on LinqToSql because, quite frankly, I want to know just where SubSonic fits in. If the ORM tool that ships with .NET 3.x does what we do, there's no reason to duplicate. SubSonic's all about improving YOUR experience, and we can just as easily wrap our loving arms around L2S just as easily as any other data access system. The challenge here isn't the technology - it's how it's supposed to be used. In other words - I have a problem with LINQ and how easy it is to stick data access code where it shouldn't go. It's twice as tempting with LinqToSql. When first created, your model practically BEGS you to let it run loose in your code behind, batting it's eyes innocently at you as it sticks the fake ID in its back pocket, ready to crawl out of your application come midnight. We've tried to make SubSonic as malleable as we can so that you, as the architect, can use its goodness wherever you please. LinqToSql sort of does this, but it's not straightforward from the get-go. I been here for years, Rockin' my peers ORM's been around a long time, and it bears mentioning right up front that
This is ORM, the Microsoft Way
I'll explain more as I go along - but keep that thought in your mind. The best explanations involve lots of code, so let's jump right in. The first thing you want to do is create a separate project. This will make sure that the protection patters we use below can be enforced. So right-click, add a class library project, remove Class1.cs (why do they put that in there?), and then right-click your project, selecting "Add Linq to SQL classes". It's a good idea to name it something relevant - like NorthwindSchema or something. When finished, you get a nice Class Diagram that lets you get your ORM on: classdiag The mapper let's you do all kinds of things - including set inheritance, relationships, naming, and so on. When you first "map stuff out", you're ready right away to do some coding. By default your DataContext class is the same name as the L2S file you created - I named mine NorthwindContext. To grab some data, all you need to do is create a context to work in, and then ask for the data:
NorthwindContext db=new NorthwindContext();
Gridview1.DataSource=db.Products;
Gridview1.DataBind();
Man, that's easy! It's actually too easy - and will tempt you into some bad habits; namely writing the code above. Puttin' suckers in fear Every project is "small, quick and simple" at some point - even for the prototype. That's not a license to be sloppy, and often the compromises made to run out a quick prototype never get refactored out like they should (guilty as charged). While I completely agree with the Premature Optimization theory, it's still important to make sure that your skeleton approach is sound so you don't build crap on a pile of crap, wrapped crappily in crap coating. Things to pay attention to up front:
  • Abstract the Database and how you call your DB routines
  • Put your business logic in a central place
  • Keep the DB away from your UI
I'll keep the focus of this post on the Database and suggest that if you want to keep things on the simple side, go with something like a data-broker pattern, where all of your calls for data involve a static class returning data object (aka "models" or "entities" in the ORM world). I'll be using this model for the rest of the post. Makin' the tears rain down like a monsoon, Listen to the bass go boom Now that we have our model, we need to crank things down a bit. So the first thing I'm going to do is to change the namespaces of the generated code, and also reset the inheritance model. To do this, right-click in the diagram space and select "Properties" to bring up the Property Sheet, then get to settin': props Things to notice here:
  • I renamed the Context to something meaningful and I like the pattern [DBName]Context
  • I set the Context namespace to "Northwind" and the entities to "Northwind.Data" - this will help a lot when coding and keep stuff "tidy".
  • I locked down the Inheritance to "sealed" so no data objects can be extended outside the project
  • I locked down access to the Context to internal so that it can't be used outside the project
The next thing I did was to create my broker class in the same project. This is a static class that hands out data as needed by the application. I called mine "NorthwindService". From an external application (a test application for instance), your DB interface class now looks like this: visibility Nice and tight! There's no hint of LinqToSql anywhere - which is how it should be. The Data{} namespace simply exposes the entities, but no DB logic. Just how we want it. Explosion, overpowerin'; Over the competition, I'm towerin' LinqToSql exposes groups of entities using generics. So if you want to get a group of records to iterate over programmatically (in other words you're not DataBinding) you'll need to do a ToList<Type>():
NorthwindContext db=new NorthwindContext();
List<Product> prods=db.Products.Where(p => p.CategoryID==5).ToList<Product>();
This is OK most of the time, but it's a bit of a pain to work with Lists directly - especially if you want to extend them. An example of extending List<> might be for sorting, or overriding the index method. You also might want to add some business logic to a List<> - say OrderItems.AdjustQuantity() for instance. Before I work with the model, I'm going to abstract the List<> by entity - in other words I'm going to create Collection classes for the classes that need it (I probably don't need collection classes for all my tables). For this post that means the product table. Being nice and tidy, I'll create a folder called "Collections" and in it, I'll add a new class called "ProductCollection":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Northwind.Data;

namespace Northwind.Data {
    public class ProductCollection:List<Product> {

    }
}
Doing it this way locks things down nice and tight, and we've effectively erased LINQ's footsteps from our application :). Don't ever compare me to the rest; They'll all get sliced and diced In my last LinqToSql post I mentioned there was some weirdness with the way Update() works (Rick goes into it a lot here), and how the DataContext was attached to the model at the hip. This is important so I'll go into that now. Up above, in this post, I mentioned this is ORM done Microsoft's way. That's a very important thing to consider when working with the DataContext and updating data. Built into LinqToSql is automatic change tracking, with Optimistic Concurrency checks turned on. What this means is that if you pull a record from the DB, work on it, and someone else comes and updates the same record in the DB, your changes are likely to be invalid (or else piss someone else off extremely). This all works nicely in the DataContext, but I don't want that thing lurking all over my application - I want to do things in one place. This is where ORM has a shortfall - when you try to go outside it's rules it doesn't like you anymore. LinqToSql let's you work outside it's context, but if you want to keep playing with it you need to be a good developer and consider concurrency issues in your model. There are two ways to do this:
  • enable version-tracking with a timestamp field in your tables (usually a very good idea) or
  • tell LinqToSql to take a hike and leave you alone
In some ways I don't like it when technology dictates design changes, but at the same time a timestamp is a good idea for all tables with important data and in this case I have to say I'm grateful that I've been made to think about. So I'm going to add a "version" field to the Products table (type timestamp) to play ball. But I'm also going to tell LinqToSql to take a hike, and disable change tracking on the Employees table since they are the only ones (in my business case) who can update their data. I don't think it's necessary to keep adding timestamp fields to all my tables, so I get my crank going and have at the designer:
  • Open up the dbml file and find the Employees table
  • Shift-click all the columns (it has to be ALL of them - not just some of them. Not sure why this is a column setting because it doesn't work without setting for all columns) and then set "Update Check" to "Never":
updatecheck This is a nice feature since it makes you think through these scenarios. You can't gain or maintain; Unless you say my name Now let's add some code and run some tests to make sure it all works as we want to it to. To the NorthwindService class I'll add these methods to expose data to my application - you can use whatever class structure you want for this, for now I just put it into one class:
    public static class NorthwindService {

        //static single-point context builder
        static Northwind.NorthwindContext db {
            get
            {
                return new NorthwindContext();
            }
         }

        #region Products
        public static Product ProductGet(int id){
            return db.Products.Single(p => p.ProductID==id);
        }
        public static ProductCollection ProductsByCategory(int categoryID){
            List<Product> prods=db.Products.Where(p => p.CategoryID==categoryID).ToList<Product>();
            return prods as ProductCollection;
        }
        public static int ProductSave(Product p){
            NorthwindContext context=db;
            bool isNew=p.Version==null;

            if(isNew){
                context.Products.Add(p);
            }else{
                context.Products.Attach(p, true);
            }
            context.SubmitChanges();
            return p.ProductID;
        }
        #endregion

        #region Employees
        public static Employee EmployeeGet(int id) {
            return db.Employees.Single(e => e.EmployeeID == id);
        }
        public static int EmployeeSave(Employee e) {
            NorthwindContext context = db;
            bool isNew = e.EmployeeID == 0;

            if (isNew) {
                context.Employees.Add(e);
            } else {
                context.Employees.Attach(e, true);
            }
            context.SubmitChanges();
            return e.EmployeeID;
        }
        #endregion

    }
Notice the ProductSave() method - by using a timestamp field called "version", I know whether it's been newly created. I could test the primary key value as well, but this type of thing doesn't always hold. The Customers table, for instance, uses a char(5) value for customerID. Since I have that timestamp field for Products, I can run the attach() method and Linq wont' complain. Also, since I told Linq to cheese off with regards to checking the Employees table, EmployeeSave also works, but I still have an issue. The check of the Primary Key is not really a good way to gaurantee that the passed in class is new. Currently this type of state checking isn't available in LinqToSql (that I've seen). To get around this I can create a set of partial classes for all of my objects and hook into their events to set some properties - but that's Fudge (note the capital F). The other thing I can do is to set something that LinqToSql should have set for me in the first place - the Read Only property for the primary key (it should be set to true - it's not by default): idcheck Much better - now we can reliably check EmployeeID (if it's 0, it's new) - there's no set accessor any more so people can't set this value. I'm gonna knock you out; Mama said knock you out You can plainly see where Microsoft doesn't want to lay tread on your turf, and they've always been that way (for better or worse). SubSonic, on the other hand, is all about convention and I can see how we can wrap LinqToSql nicely, generating things (and resetting settings) to wrap your schema. We could also generate up a set of partial classes for each Linq entity and throw in some state checks that are a little more explicit (like IsNew), and also do an audit of the schema to make sure your plan will play ball with Linq. You can see that this means moving from helper to more of an architectural standard, which in some ways is OK with me. I'd love to hear your thoughts on this!

Technorati Tags: , , ,

Stephan Vinkenborg avatar
Stephan Vinkenborg says:
Wednesday, August 22, 2007
Nice article. I was wondering the same about the update check being a column setting but then I remembered that in the old dataadapters they did optimistic concurrency by checking all the column values in the update statement. You actually had to do some stuff to change that for timestamp checking. That might be the way they did it here too.

Remmus avatar
Remmus says:
Wednesday, August 22, 2007
As I read through this post I thought. Hmm nice, yeah, yeah, ok, right, this is all straight forward but time consuming and tedious. I wonder if SubSonic could do this for me. Oh that's what he wants to do, sweet. I definately think this would a good direction to go in. I don't think it is worth the effort to build up SubSonic's querying tools when there is something like this you can integrate and help us use

Stuart Allen avatar
Stuart Allen says:
Wednesday, August 22, 2007
Rob, Are you thinking of having future versions of SS wrap L2S??

Damien Guard avatar
Damien Guard says:
Wednesday, August 22, 2007
LinqToSql only offers one part of the Rails stack, namely the ActiveRecord one. As Subsonic already offers more than that in terms of scaffold and all sorts of code generation I think it still has a role to play. I'd like to see it generate the data context, provide the scaffolding and add MVC on top with AJAX support. Basically the Rails stack sans ActiveRecord... [)amien

Geri Langlois avatar
Geri Langlois says:
Wednesday, August 22, 2007
One of the issues that SubSonic solves for me is that it insulates me from having to learn everything and know how everything works. It has become my "go to" for almost all data access. Don't get me wrong, I love to learn new approaches, technologies, etc. but the real job demands production. I write small to medium size web apps and ecommerce sites. The budgets for these are limited so many times I'm the sole developer/designer for these sites. As you know good UI can take alot of time. My hope for SubSonic is that it can be a stable data access layer that moves and improves but one that can provide a level of abstraction from all of the "shiny new objects" that I constantly want to grab. This would allow me to move forward, have a real job (well, sorta) and quickly develop new apps. Just my 2 cents but I have a feeling that there are many other like me out there... Thanks again for your hard work and thoughtfulness.

Jason avatar
Jason says:
Wednesday, August 22, 2007
I second Remmus' comment. I really like your approach with the static class wrapping it all up.

Adam Nofsinger avatar
Adam Nofsinger says:
Wednesday, August 22, 2007
So are Damien and Remmus suggesting that Subsonic 3.0 or 3.5 (the one that uses .NET 3.5 -- I like the sound of Subsonic 3.5) should wrap LinqToSql? This amounts to replacing code in the Query and/or QueryCommand classes? Could it be done without a lot of breaking changes? What makes LinqToSql better than Subsonics current ActiveRecord classes and Data Access classes? I'm not doubting it is, and maybe you didn't say it was, but I'm still curious. Thanks for all the research and work you are putting into this Rob. I think many people can benefit from this, not just SubSonic userbase.

David Cumps avatar
David Cumps says:
Wednesday, August 22, 2007
Great explanation and code examples, helped me to understand more where I can fit Linq in with my current design. Cheers!

sestocker avatar
sestocker says:
Wednesday, August 22, 2007
"so you don’t build crap on a pile of crap, wrapped crappily in crap coating..." Thats too funny. From a new developer's point of view, I'd love to see more architecturally focused articles. For instance, at my previous employer they did a lot of inline SQL. Something like: using (SqlCommand cmd = new SqlCommand()) { cmd.CommandText = "Select * From Products"; cmd.Connection = new SqlConnection(conn); try { cmd.Connection.Open(); cmd.ExecuteReader(); } finally { cmd.Connection.Close(); } } Could you explain the pitfalls of this type of architecture? What are the advantages to having a data access layer wrapping ADO.NET objects?

Dietrich avatar
Dietrich says:
Wednesday, August 22, 2007
When it come to Microsoft and their web programming systems my biggest problem by far is the amount of time I spend googling some strange unintuitive error that has to do with code generation and how I set or didn't set some parameter. When I see "right-click and select" in Visual Studio, I cringe. That doesn't happen to me when I use subsonic. In general it seems to me that MS tries to be too universal trying to cover desktop and web applications developmental in one shot. And their systems don't come out of a learned web application need like Rails and Subsonic. I realize you're still kicking the tires to get a feel for LingToSql, but what does LingToSql do better than Subsonic in terms of ease and elegance of web development?

josh avatar
josh says:
Wednesday, August 22, 2007
First, I like the idea of SubSonic filling in a helper/architecture role in that we need tools to make good design easier. LinqToSql is a tool that makes bad design easier. I don't like that. Many thanks to the SubSonic team for such a good product, and apparently a good direction in dealing with LinqToSql. Second, I still have reservations about LinqToSql. There is the issue of context, which you mention. (I also read a blog where its possible to re-attach to a new dbcontext if the original one was dropped.) I've also read that L2S queries are forward-only and retrieve one row at a time. So if you enumerate a list of 1000 products, it is actually retrieving each row as you enumerate. I really hope that's not true though... can someone confirm? If L2S is performant and does not retrieve-as-you-enumerate, then I see no problem using L2S behind the scenes for SubSonic. In fact, I'd rather like that abstraction for the benefit of good design.

Rob Conery avatar
Rob Conery says:
Wednesday, August 22, 2007
@josh - I think the issue you're speaking about is Rick Strahl's article where he talks about looping over a result set. If you define your LINQ query and then ask for a result 1000 times, yes, it will execute 1000 times. If, however, you define a query and execute the results ToList, that doesn't happen. @everyone - the thing that LinqToSql does that's nice is , well, use LINQ which is extremely powerful (next article is all about neat queries with LINQ). What I'm thinking is that a branch of SubSonic can wrap this all nicely for you - allowing you to use LINQ while still abstracting things into happy, usable packages. A GUI tool like the L2S designer is really powerful when designing up your schema. Also, the properties you can set are amazing. Foremost, however, I don't want to be in a competitive space with MS - that's just not a good thing. While I'm confident SubSonic can always offer value no matter what we do, I like the idea of using their toolset and improving on it - not going divergent directions. In this case, Linq2Sql is performant and easy to use - so let's use it!

Shawn Oster avatar
Shawn Oster says:
Wednesday, August 22, 2007
The reservation I have about including LINQ in SubSonic is I haven't fully grokked what SubSonic, and thus us developers, would gain besides another dependancy? I have scary flashbacks to when .NET first came out and a lot of people re-wrote their C++ MFC Win32 apps as WinForms. They spent a lot of time and energy porting everything from C++ to C# only to say, "Look at our application, it's exactly like it was before except now you also have to install the .NET runtime!" I'd prefer SubSonic *not* use LinqToSql or LINQ at all because it's introducing yet another layer and so far I haven't seen any strong arguments for it. It's very cool to be sure but I'm waiting for someone to give really good solid reasons *why* using LINQ inside of SubSonic would be better than what is there now.

Damien Guard avatar
Damien Guard says:
Wednesday, August 22, 2007
@adam: No, I'm not saying Subsonic 3 should wrap LinqToSql but complement it. LinqToSql is nice but it only replaces ActiveRecord in the Rails stack. Microsoft still has nothing for model-view-controller web applications, scaffolding to get editing systems up quickly, database versioning/scripts or other Rails goodness. I'd love to see Subsonic filling the gap between those stuck in WinForms/ViewState/create-another-editor hell who don't want to learn almost everything again to utilise MonoRail (a whole new language for templating and the NHibernate stack for data access). [)amien

Shawn Oster avatar
Shawn Oster says:
Wednesday, August 22, 2007
@Rob - Based on your last comment it sounds like you've already decided to use Linq2Sql :) I'm still against though as I haven't seen any compelling reasons to use it. Here are my concerns and questions: 1. Based on your tests LINQ seems marginally faster than what SubSonic is currently using. Not enough of a speed increase to actually warrant the time it'll take to swap it in. 2. If you rework SubSonic to use LinqToSql what do SubSonic users gain, from a specific SubSonic framework vantage point? Does how we work with SubSonic change? Do we get new methods? Do old ones break? I don't care about LINQ, I care about SubSonic, what benefits as a SubSonic user will I see if you use LINQ? 3. I don't see SubSonic as a competing architecture to LINQ. They are two different approaches as you yourself point out. 4. In the grand scheme of things I care a lot less about LINQ than I do say about migrations or REST or Sqlite3 support. 5. What issues does using LINQ address? Are there great gaps in functionality that LINQ will fill or are we just swapping one back-end for another? If so what's the point? 6. Will using LINQ mean we have to configure yet *more* things before we can start using our ORM? The thing I love about Rails is you just go, with maybe a small tweak to your database.yml file. Adding any more configuration steps to SubSonic turns it from a nice, compact, *simple* framework into yet another framework in which you must become a master before you can even get up and running. The entire reason I switched away from NetTiers was because you had to wade through so much configuration. Now I'm not down on LINQ, I just think someone should play devil's advocate here. The bottom line question is are you hot on LINQ just because it's cool and want to use or do you truely believe that using LINQ will make the average SubSonic user's experience better?

Rob Conery avatar
Rob Conery says:
Wednesday, August 22, 2007
@Shawn: nope, haven't decided anything, just musing :). To answer your questions... 1) LINQ isn't necessarily faster - they're about the same. In terms of swapping in - this is only for 3.x projects and we're not going to change our current track WRT 2.0. In other words there won't be any breaking changes here - hopefully just the choice to use LinqToSql. 2) You gain the ability to use Linq :) and a graphical model designer - which is pretty nice. Again, we're not going to wholesale replace anything - just augment what MS is offering for 3.x (if at all). 3) Somewhat - but if we're both doing ORM... 4) Yep, me too. Wouldn't it be cool to add that on TOP of LINQ? 5) There are some nice model abilities that LINQ adds - such as read-only columns, concurrency checks, typed SPs, etc. Also the LINQ query tool is pretty complete and well-documented :). 6) L2S is pretty drag n drop with just about no configuration. If SubSonic wrapped it, we'd go in and monkey with stuff as well so ideally it would be the same experience that you have now. I hear you - good questions, all of em. My goal is not to "gut" SubSonic - just push some of it's magic into LINQ.

denni avatar
denni says:
Thursday, August 23, 2007
NorthwindContext db=new NorthwindContext(); Gridview1.DataSource=db.Products; Gridview1.DataBind(); Man, that’s easy! It’s actually too easy - and will tempt you into some bad habits; namely writing the code above. --- Rob, how LINQ will tempt us into some bad habits any more than SubSonic. SubSonic also allows us to do the above things even easier. Gridview1.DataSource=Products.FetchAll(); Gridview1.DataBind(); Why writing the LINQ code in the UI worse than writing the SubSonic code? Or are you also implying that SubSonic offers the same level of the temptation?

Rob Conery avatar
Rob Conery says:
Thursday, August 23, 2007
@denni - it's true in both cases and is one major reason I created the MVC templates. Eric and I have always tried to stay away from architecture issues - but this is going to change. The thing with LINQ is that the DataContext actually makes it harder to put everything in an abstracted bucket (see my last post)

denni avatar
denni says:
Friday, August 24, 2007
I agree that DataContext brings some pains when updating the database, been there my self. But I also like how LinqToSQL allows to hide the DataContext from other classes, unlike the fact that all SubSonic-generated methods related to data acess (i.e., Save(), FetchBy*(), Delete()) are public. I have to modify the code template so SubSonic will generate protected methods instead, so I can expose my models without data acess functionalities (which I will build on separate controllers or services). I already watched your MVC templates and it's pretty good, hope it will ship with the next version of SubSonic. However, as you stated earlier that you just wanted to help, not dictated people how to build their solution, it would be great if the MVC generator will only be an option, not the only choice of the template. So people won't be forced to use MVC when using SubSonic. Thanks Rob, looking forward for your smart (as usual) solutions.

ESICO avatar
ESICO says:
Friday, August 24, 2007
hmm.. nice article Yesterday wen I felt a little tired and feeling a bit sceptical I was reading this nice article about L2S and I agreed with most of the code and a lot of comments made perfect sense. The first post of Shawn about win32 to .net conversion made me laugh. I had a similar experience. Yes sure, we can create an extra layer (wrapper) and use the linq stuff but what do we gain? - a nice graphical model designer? I have a subcommander button which will do the same stuff (actually I had pressed that button half way your article), easier in less time - ok maybe we could install the buttons when installing SS. Don't get me wrong the designer is very neat but I really can live without it. - .NET 3.5 bloat Yes you need to install this and it is normally not a problem but if I don't have to I will stick to .NET 2 because of the smaller footprint. - Transparency SubSonic reminds me of developing with Delphi. When an application had problems I could debug it thoroughly, even the components libray (the VCL). This also applies to SubSonic. I'm not so sure about this with L2S. - Query tool Subsonic has a nice one and the L2S is probably better but is it that much better? - And more which already are mentioned. Anyway I also read Scott Gu's articles and I can see that L2S is nice but I think SubSonic just shines more brighter and in Technicolor because it does its job fast, elegant and reliable. Linq is of course more than L2S and I think it is very promising technology but for me it shines most in Linq2XML and Linq2Collections. Thanks 4 those nice readings

Michael Giagnocavo avatar
Michael Giagnocavo says:
Friday, August 31, 2007
I wrote a tiny library that lets you easily create the basic add/insert/update/delete methods for each table: http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx Then your code can look like: MyDatabase.Things.Update(myThing); It's also useful to define DataContext helper methods such as "Query". This lets you do such things: var item = MyDatabase.Query(dc=>dc.Things.First()); Instead of having to explicitly declare your item outside of the DataContext using block.

Oskar Austegard avatar
Oskar Austegard says:
Saturday, September 15, 2007
Eric "CodeSmith" Smith released Plinqo a while back - as I know you've been a long time CodeSmith user I was curious what your thoughts on it are?

Fero avatar
Fero says:
Sunday, October 14, 2007
Hi Please help me. Your collection: namespace Northwind.Data { public class ProductCollection:List {} } Use: public static ProductCollection ProductsByCategory(int categoryID) { List prods=db.Products.Where(p => p.CategoryID==categoryID).ToList(); return prods as ProductCollection; } Returns null. If you use like this return (ProductCollection)prods; Throws Unable to cast object of type 'System.Collections.Generic.List`1[Northwind.Data.Product]' to type 'ProductCollection'.

Mike avatar
Mike says:
Tuesday, October 30, 2007
"The thing with LINQ is that the DataContext actually makes it harder to put everything in an abstracted bucket (see my last post)" Huh, how's that? You wrote a post explaining just how to do that, so it's not _that_ difficult, right? In fact, it's more difficult with SubSonic because of the ActiveRecord classes. If you return those, then you return an object that can be used to directly change the database, without going through logic and validation. Isn't that exactly why you created the experimental new MVC templates?

 avatar
says:
Thursday, December 13, 2007
Cumhot Free Movies... Dailey Taylor small keeps christian Tasty Tara Luna Lane. Dishes minister earth seemed mouth latest? ...

 avatar
says:
Wednesday, December 19, 2007
Sxy Models... Masty naked fill? Main beautiful won't sxy models expects! ...

Pálesz avatar
Pálesz says:
Monday, January 07, 2008
Why don't you put the methods from the NorthwindService into a partial NorthwindContext class? What's the reason?

Mike avatar
Mike says:
Friday, January 11, 2008
Hi Rob I have been playing with your example as I have had loads of problems with databasecontext and attach I have kept it super simple and used your code - with minor changes so it works with RTM but I still get an error when I write ... (I have added the version field (timestamp) as you suggested Product p = NorthwindService.ProductGet(1); p.ProductName = "testing"; NorthwindService.ProductSave(p); I get NUnitTests.NUnitTests.Test2 : System.NotSupportedException : An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported. I can "fix" the problem by keeping a single databasecontext alive but this is just a simple test I want to get a product - then later allow it to be updated and the only way to keep a single databasecontext available I have read numerous other blogs about this and cannot seem to find a clear way forward. I am(was !) just about to teach this stuff to a group of Masters students but am not sure now - might go back to Wilson ORM or Subsonic Thanks for any help Mike

Bill Deihl avatar
Bill Deihl says:
Sunday, January 20, 2008
Hi Rob. It would seem you have stirred some discussion with this post. Good work as always. The image links on your post is broken; I think they would help me understand some of the directions here. Best of luck! Bill

Donn Felker avatar
Donn Felker says:
Thursday, March 20, 2008
Hey Rob, Great articles, I was wondering if you could update the images. They seem to be broken. Thanks again! Donn


Search Me
Subscribe

Index Of MVC Screencasts

You can watch all of the MVC Screencasts up at ASP.NET, and even leave comments if you like.

Popular Posts
 
My Tweets
  • @haacked must.... resist... assimilation...
  • Dinner at the Haacks. How did Phil get such a cute kid? Evidently Phil's in the doghouse though...
  • @shanselman dude turn off twitter and drive! that's gotta be illegal!
  • For D'Arcy and Justice... Scottgu goes Canuck! http://twitpic.com/mfz1
  • Working in ScottGu's office with @shanselman. Wearing an Orange Polo and saying "go ahead" a lot for some reason.
  About Me



Hi! My name is Rob Conery and I work at Microsoft. I am the Creator of SubSonic and was the Chief Architect of the Commerce Starter Kit (a free, Open Source eCommerce platform for .NET)

I live in Kauai, HI with my family, and when my clients aren't looking, I sometimes write things on my blog (giving away secrets of incalculable value).