No CRUD on entity please (aka anti-pattern of DB access methods on data/biz object)


I keep getting this question so often – “I want to do xyz. I have CRUD (Create, Read, Updated, Delete) methods on my entity class ….”


Stop right there. By now I have completely forgotten about “xyz” and I am rushing to climb on my soapbox!


While designing LINQ to SQL, we went to great lengths to avoid or at least minimize any coupling of an entity to data access operations (CRUD). This lets entities behave like data or business objects and makes them mobile from mid-tier to client. The whole point was to avoid having to dump the kitchen sink and its crud into the entity. Looks at wrapper methods for sprocs, override methods for CUD, Table<T> methods, SubmitChanges() or Attach(). All of them are _away_ from entities. This is not an accident! There are several reasons behind it:



  1. As mentioned above, this provides a better logical organization – the data and associated methods that manipulate the data in entity class and the persistence service in a separate class.

  2. Entities can be moved between tiers much more easily. Connecting to database from presentation tier is either unadvisable or simply not permissible. With the separation mentioned above, DataContext stays on the mid-tier while entities move around as needed. (We haven’t done nearly enough in this area to make it even simpler but we have laid the foundation at least)

  3. (This is often negelected but important) The persistence operation is structured around a unit of work. If you modify multiple entities, you don’t have to create another unit of work that calls the update methods on all the entities or even all entity classes. Just DataContext.SubmitChanges() is enough and it is done transactionally and with optimistic concurrency checks in that transaction.

To be blunt, if you are going to use LINQ to SQL, please don’t fight the pattern it was designed for. The proverbial square peg of CRUD methods on entity is just not going to fit in the round hole of the DataContext as CRUD service provider design.


Now that this is out of the way, we can talk about the “I want to do xyz” part instead 🙂


Dinesh


 


Comments (5)

  1. I keep getting this question so often – "I want to do xyz. I have CRUD (Create, Read, Updated, Delete)

  2. Rohit says:

    Dinesh.

    Regarding your point #2, I hope you would support segregation of DataContext and entity classes. Currently the beta2 designer supports segregation of namespaces. I use sqlmetal to generate a DBML file and then customize the DBML for seperate namespaces (DataContext goes into Project.Data [DAL] and entity classes go into Project.Data.DTO). The intention is to have the entities traverse across layers and possibly tiers. I have to manually cut and paste the DataContext as of now.

    1) I might consider developing a custom tool if its not supported in the RTM version of sqlmetal or designer. Please let me know.

    2) For SOA the current functionality of packaging entities and DataContext into 1 file might make sense due to a) serialization b)Access control c)versioning of entities creating an impact to the client.

    I have written in greater detail in this article –

    http://www.codeproject.com/cs/design/EnterpriseApplicationArch.asp

    Thanks

  3. Dinesh.Kulkarni says:

    Rohit,

    Very impressive article! It is really gratifying to see so much thinking going into various aspects of design. I scanned it a short while ago but I will have to sit down and read it further.

    I agree with you regarding the next step that should be taken. Generating separate files for DataContext and entities that can be packaged separately makes sense. Lack of this feature is a limitation in V1 indeed. It is not the design intent and is very consistent with what I would have personally liked to see.

    It is not supported in RTM version of either tool.

    Thanks,

    Dinesh

  4. I keep getting a lot of questions about whether DLinq is for data objects or for business objects. There