Geeks With Blogs
Andrew Siemer's Blog Enterprise Web Applications, ASP.NET MVC, C#, SQL Server, Architecture, & Writing

I have been working for the past few days to try and figure out how to get LINQ to SQL integrated into my normal nTier environment. I have also been trying to follow along with the general principles of Domain Driven Design but am finding that there are some deficiencies in the current LINQ to SQL implementation that force a few restrictions on how I do things.

Let's first look at some of the restrictions

Disconnected DataContext

My understanding of the LINQ to SQL DataContext is that it prefers to remain open.  The primary reason for this is that its sole purpose in life is to track the state of it's objects.  As you add new objects into your collections, modify existing objects, or delete objects, the DataContext is tracking everything.  Then you can all DataContext.SubmitChanges() and it will persist all of those changes into the database.

Keeping a DataContext around for the life of a web application though just doesn't sound realistic to me!  I am very much used to the idea of opening a connection to the database, getting in, getting my job done, and getting out.  As soon as I start down the standard tiered way of thinking where I open my DataContext, get an object, close the DataContext, do some work on my object, open a new DataContext, persist my object, and finally close that DataContext - LINQ to SQL is very unhappy with me!

This is just not the way that LINQ to SQL is currently designed to work!  There are many work around's to get it to work the way it was intended, but it seems to add a level of complexity to the system that I think is inappropriate.

Interesting reading:

LINQ to SQL DataContext Lifetime Management

LINQ to SQL and attaching Entities

Simple object relationships

When I think about LINQ to SQL I am thinking that I have a whole ORM system similar to NHibernate that allows me to fetch an object and it's children, make some changes, push that back into the database, etc.  All seamlessly!  That has not been the case so far. 

I am finding that LINQ to SQL doesn't like working with complex relationships.  This is primarily due to my working in a disconnected environment of course.  I am told that if I were to just use one DataContext that I keep alive forever - all would be fine.  I am a web developer though - not a desktop guy!  This just isn't possible.

This leaves me to managing my own relationships between my objects.

Persisting child objects

In the same way that I would think LINQ to SQL would allow me to fetch and play with child objects I would think it would allow me to easily persist them.  This too doesn't appear to be the case.  When spinning up a new DataContext I have to first detach all my children objects from the parent object, then attach the parent to the DataContext, then attach the children object to the parent object, and then SubmitChanges().  This is not always 100% though!

Value Objects

Entities and Value Objects are a very important part of Domain Driven Design.  A value object is basically an object that can't exist without a parent object (or Entity).  It doesn't have any unique identifier by itself.  Where as an Entity object can exist without any help from other objects.  As far as LINQ to SQL is concerned, all objects are to be Entity objects.  This makes sense considering that LINQ needs a unique identifier in order for it to do it's job efficiently.  However, this breaks some of the concepts of Domain Driven Design!

Now let's look at how we can get around these issues

Disconnected DataContext

When working with a disconnected nTier environment we need to be able to spin up a connection to the database, do some work, and disconnect - freeing up resources and going on our marry way.  LINQ to SQL provides some features that allows you to do this as long as you are aware of the surrounding issues with making this decision.  LINQ to SQL provides you with the Attach() method.  There are various overrides of Attach(), but the one we are most concerned with is the one that allows you to specify that the object you are attaching already exists and that you are attaching a modified version of it.

dc.Respondents.Attach(respondent, true);
dc.SubmitChanges();

Simple object relationships

To be totally honest with you, the easiest way I have found to work with LINQ to SQL and how it manages relationships regarding my objects is to simply remove all knowledge of my relationships.  At first this may sound a bit off, but it really does work out quite well in a Domain Driven Design where my repositories are responsible for simple fetching and persistence functionality and my services are more concerned with managing the relationships of my objects.  As soon as I decided to use LINQ to SQL in this manner, everything started to work without any problem.  No more hacked work around's to try and get it to perform as advertised!

Persisting child objects

As stated above, now that LINQ knows nothing about how my objects are related to one another, I no longer have to worry about this as an issue.  I can now directly handle my relationships at the service layer above my repositories.  If I need to save a complex object with child objects, I can pass it to a service layer which will break it apart and save out the underlying objects.  This gives me total control at this point.

Value Objects

I have yet to find a fix for this issue!  LINQ requires that our objects are unique in the system on their own merit!  I doubt this will ever change.

Putting it all together?

Now that we know about the pros and cons of LINQ to SQL in a tiered environment and understanding my suggested work around's, lets see it in action.

Connection Wrapper

My connection wrapper may be a bit more complex than you might need.  It is set up to work in an automated building/testing environment where NAnt is in control of which connection string to use.

 

using System;
using System.Xml;
using Company.Project.Core.Domain;
using Company.Project.Core.Properties;

namespace Company.Project.Core.DataAccess.Impl
{
    public class Connection
    {
        public ProjectDataContext GetContext()
        {
            string connString = "";
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load("ConnectionStringToUse.xml");

                XmlNodeList xnl = doc.GetElementsByTagName("environment");
                XmlElement xe = (XmlElement)xnl[0];

                switch (xe.InnerText.ToString().ToLower())
                {
                    case "local":
                        connString = Settings.Default.ProjectConnectionStringLocal;
                        break;

                    case "development":
                        connString = Settings.Default.ProjectConnectionStringDevelopment;
                        break;

                    case "production":
                        connString = Settings.Default.ProjectConnectionStringProduction;
                        break;

                    default:
                        throw new Exception("No connection string defined in app.config!");
                }
            }
            catch
            {
                connString = Settings.Default.ProjectConnectionStringLocal;
            }

            ProjectDataContext fdc = new ProjectDataContext(connString);
            return fdc;
        }
    }
}

This of course could be greatly simplified to just return the default DataContext!

Once we have this in place we can start creating a repository.  A basic repository should provide ways to get an object by ID, save an object (inserting and updating), and delete an object.  It might look something like this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Company.Project.Core.Domain;
using Company.Project.Core.Properties;
using StructureMap;

namespace Company.Project.Core.DataAccess.Impl
{
    [Pluggable("Default")]
    public class RespondentRepository
    {
        private Connection conn;
        public RespondentRepository()
        {
            conn = new Connection();
        }

        public Respondent GetRespondentByID(Int32 RespondentID)
        {
            Respondent result;
            using (ProjectDataContext dc = conn.GetContext())
            {
                result = dc.Respondents.Where(r => r.RespondentID == RespondentID).First();
            }
            return result;
        }

        public void SaveRespondent(Respondent respondent)
        {
            using (ProjectDataContext dc = conn.GetContext())
            {
                if (respondent.RespondentID > 0)
                {
                    dc.Respondents.Attach(respondent, true);
                }
                else
                {
                    dc.Respondents.InsertOnSubmit(respondent);
                }
                dc.SubmitChanges();
            }
        }

        public void DeleteRespondent(Respondent respondent)
        {
            if (Settings.Default.PerformActualDeletes)
            {
                using (ProjectDataContext dc = conn.GetContext())
                {
                    dc.Respondents.DeleteOnSubmit(respondent);
                    dc.SubmitChanges();
                }
            }
            else
            {
                respondent.FlaggedForDelete = true;
                SaveRespondent(respondent);
            }
        }
    }
}

The only thing that is not standard C# code here is the reference to StructureMap and the attribute of [Pluggable("Default")].  For more on what StructureMap is look here:

http://structuremap.sourceforge.net/Default.htm

To get started with our repository you will first notice the constructor for this class is spinning up a new instance of our Connection object.  This is important as each method will need to be able to speak with the database and they use the Connection object to do so.

From there we have a GetObjectByID method.  This will perform the basic fetch functionality that all systems need.

public Respondent GetRespondentByID(Int32 RespondentID)
        {
            Respondent result;
            using (ProjectDataContext dc = conn.GetContext())
            {
                result = dc.Respondents.Where(r => r.RespondentID == RespondentID).First();
            }
            return result;
        }

One thing to notice here is that we are spinning up our DataContext inside of a using statement.  This means that the DataContext will only exist in that using statement and will be disposed of when we are through with our work.  We then call conn.GetContext() to get an instance of our DataContext.  As this is a simple selection operation I have used a Lambda to grab the record with a corresponding ID and then called .First() to insure that we will only be returning one object.  Since we are using a unique ID I should only be returning one object anyways...but better safe than sorry!  Keep in mind that when working with LINQ, some methods are deferred and the scope of the DataContext is local to the using statement.  This means that if you want to return a result set or an object you may need to create a variable that is a bit farther reaching.  In our case we declared a Respondent object which is then passed out of the method.

We then get to our SaveRespondent method.

public void SaveRespondent(Respondent respondent)
{
    using (ProjectDataContext dc = conn.GetContext())
    {
        if (respondent.RespondentID > 0)
        {
            dc.Respondents.Attach(respondent, true);
        }
        else
        {
            dc.Respondents.InsertOnSubmit(respondent);
        }
        dc.SubmitChanges();
    }
}

This method is responsible for both inserting new objects and saving existing ones.  The make up of how we retrieve an DataContext is the same as before.  In this case though we want to test the passed in object to see if it has an ID already or not.  If it doesn't have an ID then we will insert the item into the database.  Otherwise we will save it to the database.  We then SubmitChanges() to actually perform the persistence.

The only thing left is to provide a way for us to easily delete an object.

public void DeleteRespondent(Respondent respondent)
{
    if (Settings.Default.PerformActualDeletes)
    {
        using (ProjectDataContext dc = conn.GetContext())
        {
            dc.Respondents.DeleteOnSubmit(respondent);
            dc.SubmitChanges();
        }
    }
    else
    {
        respondent.FlaggedForDelete = true;
        SaveRespondent(respondent);
    }
}

Again, the make up of how we obtain a DataContext is the same.  There is a bit more code here than is necessary.  Technically all you need is what you see in the using statement.  However, I have baked in some extra logic here that asks are we performing real time deletes or system/batch deletes later. The basic real time delete logic is this:

using (ProjectDataContext dc = conn.GetContext())
{
    dc.Respondents.DeleteOnSubmit(respondent);
    dc.SubmitChanges();
}

The Settings.Default.PerformActualDeletes is simply a flag to determine where we are going to do the real time deletes or not.  If we are not doing real time deletes then we update the FlaggedForDelete property to true.  Then a custom process would clean out the FlaggedForDelete objects later in the evening.

Once all of these methods are in place you can then start building services on top of the repository if you feel you need to.  For the most part these simple repository methods should meet your needs.  But in the case that you have a complex object, you may need a service to assemble it or disassemble it and persist it's children to the database via the repository.

Posted on Tuesday, February 5, 2008 2:52 PM | Back to top


Comments on this post: LINQ to SQL - Implementing the Repository pattern

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Question: What is different between creating the connection each time vs. creating the datacontext each time?
Left by Steve on Feb 06, 2008 8:13 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
They are one in the same when speaking about LINQ to SQL. The DataContext is what actually handles the connection to yoru database among many other things.
Left by Andrew Siemer on Feb 07, 2008 9:31 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Andrew, great post I have been chomping at the bit to start using Linq in a detached N-Tier but have simply come up against the "this is totally jury rigged" block that so many people have regarding attaching. Some questions (I started here by writing two then had to go back as my curiosity just didn't stop).

1. In your method, I assume you are still using the timestamp method on your tables to retain optimistic conc. no?

2. I have tried to find it, but did ScottGu ever end up posting on this whole attach issue on his blog like he said he was going to?

3. What do you think of Rick Stahl's assertion that even with all these problems figured out the Linq n-tier pattern is still 3x slower than even typed datasets due to the inherent reflection in Linq entities?

4. Where are you doing your link up of objects on Foreign keys? Are you adding properties to the DBML file and then filling the props, doing multiple queries in your presentation layer, or some other way that I am not thinking of?

5. With all these issues, is Linq even worth it?
Left by JasonJ on Feb 08, 2008 6:04 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
1) Yes, I am using a timestamp column in all of my tables so that I can reattach my objects easily. Oddly enough I just came across a reminder as to how important this was regarding LINQ more than the concurrency issue. For some reason I was losing my timestamp value (or it was showing as null in the SQL that LINQ generated) so LINQ rejected my attempts to update the given object. As part of getting this issue I removed the timestamp column to see if I could possibly move past the issue...as I had the ID of the object that I wanted to update. LINQ complained more about this idea though! So I ended up getting the object and passing my updated values into that object prior to passing it back in to the DataContext. Essentially...the timestamp must be present and must not be null! <GRIN> So in terms of disconnected environments you either need to save the timestamp as you would an objects ID...or save the object...so that you can reconstitute prior to reattaching it. Or re-get the object at the time you want to update it. TIMESTAMP IS VERY IMPORTANT.
Left by Andrew Siemer on Feb 08, 2008 7:19 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
2) Not sure about that. I have basically gone down the road that every fix I have seen is a hack to something that should have been part of LINQ to SQL prior to being released. However, it wasn't. What I am seeing is that persisting child objects in LINQ based on the relationships that it is aware of in a disconnected environment (tiers...) is just not something that LINQ is yet ready to do! So my fix to that, rather than trying to make a backward hack for it is to just remove all the links in the DBML file and manage the relationships myself. So far this has worked very well! I try to follow the DDD concepts using simple repositories and services (application layer) to assemble and disassemble my objects as needed. While this is in no way what I am used to with NHibernate...LINQ is still easier for persistence. I have yet to write a lick of SQL...which goes a long way in a rapid development project! It is not perfect...but it is better! And far easier to work with than other ORMs...even though it is not yet feature complete.
Left by Andrew Siemer on Feb 08, 2008 7:19 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
3) No relationships should remove some of the strain that LINQ has to deal with. On top of that...no matter how the data is brought into the application, most of it can be cached to some degree or another. So if it takes 3 times longer to get data...every now and then...but is 100 times less work to actually build and get running...I will still use it. Also, I am sure that any speed issues will be delt with over time. If you want truely optimized code then you will most likely stick with a single query to return all that you need in the most optimized format. If you need easy to work with and quick time to market...you will work with LINQ or NHibernate. Also...and this is the biggest bonus in my eyes...if you want something that is easily refactored with minimal changes to the system then LINQ is even better than NHibernate! Just depends on your needs...as with most things.
Left by Andrew Siemer on Feb 08, 2008 7:20 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
4) Unfortunately I doing a form of multiple queries...but not out at the presentation layer. This is where the repositories and services layers come in. If it is a log in process I am using a service. This service might take in the user supplied username to fetch the Account object and use the returned AccountID to also fetch the list of permissions for that user. If the password that was also supplied matches the password attached to the retrieved account matches and the permissions are correct...we are off and running! While this is far from the most "efficient" way of doing things...I retain the control, can use LINQ to SQL easily, and am able to follow DDD concepts pretty well. Again, if the user is correct I will stash that into cache and be on my way! Keep in mind though that you can write a complex query in a proc and call that with LINQ, then parse the complex data that is returned and hydrate your objects that way. Though I prefer repositories and services for something large in scale...with a good cacheing approach.
Left by Andrew Siemer on Feb 08, 2008 7:20 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
5) Again, LINQ isn't the silver bullet for all cases. I am using it on two large scale projects currently. Once I realized how lacking it was with regards to ORM and decided to change my thoughts on how I should use...primarily for hydrating and persisting "OBJECTS" (read: not just data) I was set. I no longer think - wow this sucks - I just love how easy it is to add a new table to my database, drag it to the designer, have an object created, and immediately be able to work with it in my app. No more creating a table, writing a proc for inserting, updating, deleting, selecting this way or that. Then creating some wrapper for all those procs. Then writing all the code that hydrates hydrates my object. Then creating the object itself. Then finally creating my repositories and services. Create table, drag to designer, create repository. DONE. Don't get me started regarding refactoring code! If you are not using LINQ to SQL...you would then have to re-touch all of those other areas...rather than just updating the table, updating the designer, updating the repository. For rapid development - LINQ to SQL flat out rocks...even with its limitations!

Give it a try...it will certainly benefit your tool box on some project!
Left by Andrew Siemer on Feb 08, 2008 7:21 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Thanks for the responses, I really appreciate the time you took to answer all of them, hopefully they will help someone else too. I tend to agree with you in terms of using linq as a simple mapper. I guess when I see a new piece of technology I try to use it for everything that is it *supposed* to do and go geek crazy when I hit roadblocks to having the perfect situation. I guess I will just have to lower my expectations of writing 50% less code to only writing 30% less code.

By the way, what do you think of the new strategy folks are using that puts the datacontext in the HTTP thread context? Stahl said a couple months ago that the Datacontext object wasn't really meant for this and performance could suffer, but last week he came out with a tutorial on it.

Thanks for your help!
Left by JasonJ on Feb 10, 2008 8:25 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I will have to take a look at it. I love his articles...so I am sure that it is a good read. However, to follow good design I would think at first that keeping your DataContext alive for every active user on your site would have some serious performance issues? I would think that it would be better to stick with spinning up the DataContext when and only when you need it. Perhaps this is worth some testing?
Left by Andrew Siemer on Feb 11, 2008 4:14 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I don't know if this is the same as the 'HTTP thread context', but I always put my DataContext object in the HTTPContext Items collection, so that a single DataContext object persists for the entire duration of a single HTTP request. Eg.

if (HttpContext.Current.Items["key"] == null)
{
HttpContext.Current.Items.Add("key", new MyDataContext());
}
return (MyDataContext)HttpContext.Current.Items["key"];

I stick this in a method somewhere and get all my web apps database operations to get the DataContext from this method. This is done mainly for convience as I can be assured that all my entities come from the same DataContext.
Left by Dominic Pettifer on May 06, 2008 4:44 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Very cool idea. How is that performance wise? Have you tried persisting it to a cache cloud such as MemCached or other? How big is a DataContext over time I wonder....
Left by Andrew Siemer on May 06, 2008 6:52 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I was hoping to see some code of how you manage your relationships manually, as you stated in the post.

Does a d/l of the code exist or is it really that trivial?
Left by rybolt on May 07, 2008 4:03 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
By managing I am referring to maintaining enforced relationships on my database. I then, from a design perspective, maintain data integrity manually. If I really need to expose a list of children say a Question and it's Answers, I can add a List<Answer> to my partial Question class and load the Answers from the repository. I would actually make a call into a QuestionService class rather than a QuestionRepository as the QuestionRepository only knows how to work with Question data/objects. The QuestionService would know that what I really want is a Question AND it's Answers. The Answers would come from the AnswerRepository. So I could technically pass a list of QuestionID's into the AnswerRepository.LoadAnswersForQuestions(List<int> QuestionIDs) method and get back a list of fully populated Questions.

If you need code let me know but I think this sums it up.
Left by Andrew Siemer on May 07, 2008 4:17 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Very interesting read. I'm just starting out with LINQ and as many others I've ran into similar issues like a repository etc.
Normally I use a very strict set of rules regarding CRUD and in the past I've allways coded with SP's and created my own objects... what a deal :)
However as I read more and more LINQ i'm getting hooked at the idea -> K.I.S.S.

Your articel was very enlightening, and YES, please write something about maintaining your data integrity, some code to describe parent-child.
Left by Janus on May 20, 2008 10:38 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
The idea of a normalized repository like this is great in theory but breaks down in practice because it has no consideration for persisting multiple heterogenous objects at the same time (aka transactions). A good usable persistence layer should allow you to take a bunch of objects, make a bunch of changes dictated by the domain behaviour, and then push the lot back to the layer for a commit. This can't happen if persistence is normalized according to type like this. To get around this problem you need to make your repository generic, and that means some sort of common base class or some kind of reflection based persistence, just like how most of the other ORMs do it. I'm guessing there is a way to hook into the metadata in linq2sql to do this but it's not really easily apparent at first glance.
Left by Dave Monk on May 26, 2008 9:57 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I have written an article related to this on codeproject

Please have a look and post your valuable comments / suggestions there.
Left by Sameer on Jun 10, 2008 3:21 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Request-scope DataContext is good idea, but it has problem with LoadOptions. There is no good solution around to resolve this issue, unless using reflection to hack it.
Left by James on Jun 17, 2008 8:46 PM

# Regarding data integrity
Requesting Gravatar...
So I have been using LINQ to SQL a LOT since I wrote this post both for my book and for my primary job. I have found the easiest way to maintain integrity is at the database level. I do this for all of my data...not just the relationships between tables. This has kept my code very clean and keeps responsilities where they should be.
Left by Andrew Siemer on Jun 21, 2008 8:04 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Good article, thanks.

I have a unit testing question about the pattern you have here. One of the benefits of DDD (as I understand it) is that the data layer can be isolated from the domain model which is usually achieved through the use of interfaces. Then it can be mocked easily with multiple repositories implementing IRepository or whatever.

However your repository doesn’t implement any interface? Does StructureMap handle this somehow instead? Or is it not possible to mock the repository for testing purposes in this case?
Left by Dylan on Jul 23, 2008 9:49 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Dylan - Yes, using repositories, even when using LINQ to SQL, you can indeed use interfaces and swap out the data layer while testing. StructureMap requires that there be an interface defined and that that interface use the [PluginFamily("YouSpecifyName")] attribute. The YouSpecifyName value is the class that will be loaded by default. This means that somewhere in your code you have a class defined that conforms to your interface that has the [PluginFamily("YouSpecifyName")] attribute. You can have as many different classes as you like, each one having a different name where [YouSpecifyName] is. This way in your tests you can load mocked/stubbed/etc. classes instead of your data access classes. Take a look at this post regarding that topic: http://blog.andrewsiemer.com/archive/2008/03/03/structuremap-101---dynamically-swapping-objects.aspx
Left by Andrew Siemer on Jul 24, 2008 12:12 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
There is something that I don’t understand in using LINQ to SQL in Repository pattern :

Let’s say that I will create an assembly for each of the Repository providers (LINQ to SQL, MySQL, Oracle, WebService, XML files etc. etc.). I will define the IRepository interface in a common assembly (let’s call it ‘Interfaces’) that will be referenced by any Repository provider assembly. But where will the entity classes (’Project’ in your example) be placed? Since they are generated by Visual Studio or by SQL Metal they would live in the LINQ to SQL provider but they are required in the ‘Interfaces’ assembly so I have a circular problem.

How do I go about this?
Left by Andrei Rinea on Oct 23, 2008 5:43 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I see your problem. For me I created the repository in the same assembly as my other core logic (entities, service/application classes, etc.). I generally stuff my dbml file (data context) into my domain directory. This effectively puts my entity classes under namespace.domain.classes which is appropriate for me. Then I can create any partial classes in the same place to extend what LINQ to SQL gives me.

In your case you truely have an issue! I would suggest that you use a product called structuremap. This would allow you to specify which objects (entity) to use in your application. This way you could define your entites for MySQL, Oracle, etc. directly in your core project as normal. But it would also allow you to build a separate LINQ to SQL set of domain objects (placeholders really - empty classes) that simple extend the generated classes with the appropriate StructureMap attributes (example: [PluginFamily("Default")] and [Pluggable("Default")]. In this way you can mostly keep your LINQ to SQL stuff (dbml file, generated classes, etc.) with itself in its own assembly.

Take a look here for seeing how to swap in other objects, assemblies, etc.

http://blog.andrewsiemer.com/archive/2008/03/03/structuremap-101---dynamically-swapping-objects.aspx
Left by Andrew Siemer on Oct 23, 2008 8:42 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Was actually informative reading. Trying to learn more about LINQ 2 SQL everyday. Thanks to people like you who are sharing these kind of infos
Left by yazılım on Mar 19, 2009 4:21 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Great article!

I realize that this is a fairly old post, but I've been wondering if this pattern / approach is possible using sprocs exclusively (something that has been mandated by my DBAs)... and it doesn't look feasible for large scale projects, unfortunately.
Left by Rusty on Mar 20, 2009 11:27 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
This pattern is used heavily in large scale applications. And yes, you can use procs exclusively but you will be performing a lot of coding tasks to perform simple CRUD procedures which sort of takes a lot of time away from coding towards the goal of the application. Plumbing coding!! That is where the power of some form of ORM comes in...it takes away the CRUD programming requirement. Also, to use procs you will need to do a lot of data transformation to get the data out of the proc result and into your domain objects. ORM does that for you.
Left by Andrew Siemer on Mar 20, 2009 2:08 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I am new to DDD and read on this post that value objects shouldn't have a unique ID, my question is simply - how does this work when persisting to the database? Is there an index on the value object table that the repository uses to reference the owning entity? I would assume this is the best way of persisting a value object to the DB and then be able to query it back up when you're constructing your object from the DB again.
Left by Miguel on Apr 12, 2009 8:41 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Generally speaking your data access layer should take care of this. The primary key is a database concept and not generally a domain concept! So tools like NHibernate would take care of this for you. So does Entity Framework. However, in the real world that we live in this non-ID concept doesn't always work! It is often times way easier to store the ID of a record in a url to the details of that object. LINQ to SQL is a case where you must have the ID present to do just about anything with a record...and therefore an object.

The idea behind a value object is that it has no purpose to exist without its parent or entity object. Take a person for example. A person has an address. The address doesn't necessarily have a person. The address (depending on your system of course) doesn't really mean anything without the person. So you should only ever look at an address when looking at the person that owns that address...or the entity that owns that value object. I agree with this most of the time...but working with IDs is something ingrained in the old ways of doing things! You can follow DDD and still use IDs...that small infraction won't kill you.
Left by Andrew Siemer on Apr 13, 2009 11:52 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I don't use aggregates simply because LINQ to SQL (with relationships removed) would be be-fuddled with them. I would need factories to construct the object as well as more logic in my repositories to de-construct the objects. I have preferred to this point (past couple of years working with LINQ to SQL) to work without relationships defined in designer. This then allows me to work with all objects as entities (as LINQ to SQL also doesn't understand Value objects). This in return keeps my service and repositories very clean and simple (though factories for complex object would be nicer - I agree). It is just where LINQ to SQL has taken me over time.
Left by Andrew Siemer on May 11, 2009 10:22 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
Thanks for the great article! Could you please point me to a place where I can download the sample code please?

Thanks again and keep up the great work!
Left by chris on Oct 29, 2009 2:12 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I am not sure I have the source code for this one any longer. However if you come find me over at DotNetSlackers.com I am writing a big series on how to build a StackOverflow.com style Knowledge Exchange type site. I am currently working on a mini-series for that that discusses architecture for an ASP.NET MVC site. The first article is a simple page direct to db example. The last article will be a 100% disconnected nTier application that follows DDD Repository WCF TDD blah blah and so on. The point of the series is how to refactor from architecture A to architecture Z so that anyone can pick up from where they are and get where they want to go. More importantly it shows the benefits of each level of refactoring.

Here is the TOC for the series: http://dotnetslackers.com/projects/StackOverflowInspiredKnowledgeExchange/
Left by Andrew Siemer on Oct 29, 2009 3:09 PM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
This article has been very helpful to me, so helpful in fact that I am reading your ASP.NET 3.5 social networking book.

I have question about removing FK relationships. Am I correct that by removing these relationships I don't have to concern myself with Linq to SQL eager loading of child rows from the database because Linq to SQL doesn't know about the child tables? I also have a question about something from your book. I hope you don't mind me posting it here since I am already posting a question here. I was wondering why your services don't call the individual Save methods within a transaction since these repositories have their own instances of the DataContext.?

Thanks


Left by Michael on Feb 26, 2010 10:54 AM

# re: LINQ to SQL - Implementing the Repository pattern
Requesting Gravatar...
I'm getting the error " An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy." on the update...
Left by Milo on Sep 24, 2011 3:51 AM

Your comment:
 (will show your gravatar)


Copyright © Andrew Siemer - www.andrewsiemer.com | Powered by: GeeksWithBlogs.net