More In LINQ to SQL with the Repository Pattern


I have figured out how to get the Repository where it does not require an active DataContext all the time. And, it works fine when run against my unit tests, so I am fairly certain it will work for me. The question I have now is whether it is the best solution. Here are my options:
 

1. Use a LINQ to SQL class with all of my entites (much like a data set)

I get two pros out of this. First, I can use a single data context, which is nice. Where this helps is avoiding too many factories:
 
IDataContextFactory dataContextFactory = new SimDataContextFactory();
 
versus
 
IDataContextFactory simFacotry= new SimDataContextFactory();
IDataContextFactory simStatusTypeFactory = new SimStatusTypeDataContextFactory();
IDataContextFactory simUploadFactory = new SimUploadDataContextFactory();
 
Second, I get generic implementation of my factory, as in the following method:
 
public IEnumerable<T> All()
{
   
using (System.Data.Linq.DataContext context = _dataContextFactory.Context)
    {
       
return context.GetTable<T>().ToList();
    }
}
 
The code here is adapted from Liam McClennan’s LINQ Repository project., with some changes I implemented due to things I read in Andrew Siemer’s blog entry. I will have to take this a bit further, as the ToList() is mandatory here, as the context goes out of scope. This means I end up having to cast as a List<T>, despite returning a list. As in the following:
 
IDataContextFactory dataContextFactory = new SimDataContextFactory();
IRepository<SimStatusType> target = new Repository<SimStatusType>(dataContextFactory);
List<SimStatusType> actual = (List<SimStatusType>)target.All();
 
A simple refactor will fix this, after I think about the implications. Currently, I see no downside to switching the interface to use List<T> instead of IEnumable<T>.
 
The downside here was mentioned in my last post. I am going to have to serve up the following object to a web service.
 
<s:complexType name="Sim">
  <
s:sequence>
    <
s:element minOccurs="1" maxOccurs="1" name="SimId" type="s:int" />
    <
s:element minOccurs="1" maxOccurs="1" name="SimStatusTypeId" type="s:int" />
    <
s:element minOccurs="1" maxOccurs="1" name="SimUploadId" nillable="true" type="s:int" />
    <
s:element minOccurs="1" maxOccurs="1" name="MobileCountryId" nillable="true" type="s:int" />
    <
s:element minOccurs="1" maxOccurs="1" name="MobileNetworkId" nillable="true" type="s:int" />
    <
s:element minOccurs="0" maxOccurs="1" name="SimNumber" type="s:string" />
    <
s:element minOccurs="0" maxOccurs="1" name="IMSI" type="s:string" />
    <
s:element minOccurs="0" maxOccurs="1" name="MSISDN" type="s:string" />
    <
s:element minOccurs="1" maxOccurs="1" name="CreatedOn" type="s:dateTime" />
    <
s:element minOccurs="1" maxOccurs="1" name="CreatedByUserId" type="s:int" />
    <
s:element minOccurs="1" maxOccurs="1" name="ModifiedOn" nillable="true" type="s:dateTime" />
    <
s:element minOccurs="1" maxOccurs="1" name="ModifiedByUserId" nillable="true" type="s:int" />
    <
s:element minOccurs="0" maxOccurs="1" name="SimUpload" type="tns:SimUpload" />
    <
s:element minOccurs="0" maxOccurs="1" name="SimStatusType" type="tns:SimStatusType" />
  </
s:sequence>
</
s:complexType>
 
This is not a big deal if I stay in the Microsoft world, but may bite me, as I have a vendor with developers who code in Java and Flex. The Flex part does not scare me much for the transfer as they can use .NET Services. They will end up pruning off the useless stuff, however.
 
Pros
  • Objects created for you
  • Generic data transport
  • Single Context
 Cons
  • Constructs in WSDL that may cause complexity in other languages

2. Use a DBML per class

The benefit here is I avoid the extra tns: elements in my web service. I still have the advantage of generic implementation, but I lose the ability to use a single DataContext. This has a potential impact on scalability, as shown below.
 

DataContexts

The dual context is not a huge concern, necessarily, but the problem will continue to grow larger as we deal with more and more objects that save.

Pros
  • Objects created for you
  • Generic data transport
  • Objects represented well for WSDL
 Cons
  • Multiple data contexts to save complex sets of objects

The big question here is how much impact do multiple contexts place on scale. In all likelihood, very little, as I do not see many scenarios with multiple objects. It does definitely impact maintainability, however, as I have to create multiple objects for each table, as not all of the code can be completely generic. Over time, I may back off on this statement, but it is the case at present.

 3. Custom Objects

This is actually a set of scenarios. Here are the pros and cons:

Pros
  • Objects represented well in WSDL
  • Full control of data transport
 Cons
  • Objects have to be coded
  • Most likely non-generic (not usre yet)

There are  many ways I can tackle this one. I can set up my objects, for example, off of a DataSet. Done this way, I can stil end up with objects that transport well, while taking advantage of the ease of loading and saving using DataSets.

Summary

This is an age old issue. If you can buy software to do your work for you, it costs far less than hiring someone to hand code it. But, you trade some amouint of control when you do this. The other option is to custom code everything, giving you full control, but control comes at a cost, as time is money. Generally you cannot sell your implementation, so it is pure sunk costs. Of the two, I prefer to lean more towards the side of buying software and tailoring it. In order to get the best of both worlds, this means finding frameworks, not components.

Ah, but Frameworks present a problem. Microsoft desires to hit as many scenarios as possible, so the box is left pretty wide. But this means I am carrying a lot of weight I probably do not need. So, even with Frameworks, I end up with a less than perfect implementation.

The answer, at this time, is probably to go with LINQ with individual DBML bits for each table. Not optimal, but it solves the most problems. The objects are simple, so they can translate well to Java. The objects are written for me, so I avoid a lot of time with boilerplate code. The methodology is well documented, evne if I am stepping outside of its box a bit, so it should be easy enough to maintain. The main con here is how to keep scale issues from biting me. As I have worked with LINQ quite a bit, I think I have a bit of a grasp on this problem.

I need to go back through my posts and see if I posted this, but the biggest gotcha with LINQ, as a data transport, is trying to work with too much data at one time. LINQ sucks when it comes to real time systems that handle tons of data. I have no intention on using LINQ for systems that need this much data, so it is not a problem. Cementing the disconnected LINQ objects will take me far on my path to using it as a generic data transport.

Most likely, I will pitch it in the long run, as I do not see LINQ being the best DAL or ORM (it can be used as a pseudo version of either). Today, however, it speeds up my development efforts. And, if I use a single DBML per table (essentially using an Active Record type of pattern with a Repository pattern to get the data), I can switch to my own objects fairly easily and without altering my web services.

Peace and Grace,
Greg

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: