LINQ To SQL and UNITY

Apr 29, 2008 at 11:41 AM
Hello,

Has anybody tried to use LINQ to SQL and UNITY? For example, in the dinnernow example, we can have a gateway that is dependendent on MyDatacontext and MyTranslators; where MyDataContext inherits from DataContext. MyTranslators depend on my Business Entities and tables.

TIA
Yaz

May 2, 2008 at 7:12 AM
There's no reason it wouldn't work. Linq DataContexts are just like any other object; just stuff them in the container and go.
May 2, 2008 at 8:31 AM
Sorry I was not clear in my question, what I wanted to know is there a best practice when using DataContext. Say I am accessing two databases SQL server and Oracle. At the moment there is no support for Oracle and thus I need some mechanism so that it is transparent and hence I am looking at an article that uses UNITY or a DI framework to make the DataContext transparent or interchangeable.
May 2, 2008 at 5:36 PM
Ah, I see. Right now, I think the best practice is to isolate most of your code from the DataContext behind a repository interface. You can then reimplement your interface to talk via Linq to SQL, Oracle, or whatever.

It's really no difference from making yourself database independent with any other technology.
Jul 21, 2008 at 7:30 AM
I've used LINQ + Unity for a couple of our projects now. I've put together a quick article on CodeProject here:
http://www.codeproject.com/KB/linq/LinqAndUnity.aspx

It works really well. I'm sure theres more robust ways to use the 2 technologies together but this works quite nicely.
Jul 21, 2008 at 6:05 PM
Edited Jul 21, 2008 at 6:07 PM


Shandem wrote:
I've used LINQ + Unity for a couple of our projects now. I've put together a quick article on CodeProject here:
http://www.codeproject.com/KB/linq/LinqAndUnity.aspx

It works really well. I'm sure theres more robust ways to use the 2 technologies together but this works quite nicely.


Hey, I read your codeproject article - good stuff, but I don't understand your big comments about having to register with a name? This test:

        [TestMethod]
        public void TestMethod1()
        {
            IUnityContainer container = new UnityContainer()
                .RegisterType<IFactory<GuineaPig>, Factory<GuineaPig>>(new ContainerControlledLifetimeManager());

            IFactory<GuineaPig> result1 = container.Resolve<IFactory<GuineaPig>>();
            IFactory<GuineaPig> result2 = container.Resolve<IFactory<GuineaPig>>();

            Assert.AreSame(result1, result2);

        }

        public interface IFactory<T>
        {
            T Create();
        }

        public class Factory<T> : IFactory<T>
        {
            public T Create()
            {
                return default(T);
            }
        }

passes just fine, with no named registration. Could you send me a small repro case so I can investigate what you're talking about here?

Jul 22, 2008 at 5:02 AM
Hey, thanks for the reply!

I think i was a bit tired writing that article... needs some updating. What was actually meant was that if you do not name your registrations in Unity then you cannot use the ResolveAll method. In my article, the Factory's Resolve method does 2 things, it registers the type in the container and returns the resolved object if it doesn't already exist in the container. If we try to resolve the same type of object more than once with the Factory object, it will check if that type already exists in the factory and if it does, it will not re-register the type (since if it did, it would return a new instance). In order to check if that type is already registered, it needs to call the ResolveAll method.

Example:

//This test shows no items in the collection returned by ResolveAll
[Test]
        public void TestMethod1()
        {
            IUnityContainer container = new UnityContainer()
                .RegisterType<IFactory<GuineaPig>, Factory<GuineaPig>>(new ContainerControlledLifetimeManager());

            IFactory<GuineaPig> result1 = container.Resolve<IFactory<GuineaPig>>();
            IFactory<GuineaPig> result2 = container.Resolve<IFactory<GuineaPig>>();

            var currItems = container.ResolveAll<IFactory<GuineaPig>>();
            Assert.IsFalse(currItems.GetEnumerator().MoveNext()); // This will fail because there is no items in the collection

            Assert.AreEqual(result1, result2);
        }

//This method shows items are returned from the ResolveAll method
[Test]
        public void TestMethod2()
        {
            IUnityContainer container = new UnityContainer()
                .RegisterType<IFactory<GuineaPig>, Factory<GuineaPig>>("TEST", new ContainerControlledLifetimeManager());

            IFactory<GuineaPig> result1 = container.Resolve<IFactory<GuineaPig>>("TEST");
            IFactory<GuineaPig> result2 = container.Resolve<IFactory<GuineaPig>>("TEST");

            var currItems = container.ResolveAll<IFactory<GuineaPig>>();
            Assert.IsTrue(currItems.GetEnumerator().MoveNext()); //there are items

            Assert.AreEqual(result1, result2);
        }


The Factory class was made for ease of use so that i can just call the Resolve method with any type that i want and it will both register the type in the container, if it isn't already, and return the resolved type ensuring that it is the same each time. This could have been done with a try catch block but that doesn't seem very good.

Perhaps a nicer way to do this whole thing could have been to use the Xml structure for Unity and just ensure all of my Logic objects are registered in the container in the Factory on each Factory instantiation, then i wouldn't have to worry about the resolve method performing 2 tasks.

Feedback is much appreciated! (I'll update the article too :)
Jul 22, 2008 at 5:37 AM
Ahh, I understand what you're saying. And for what it's worth, that behavior was a deliberate design decision.

Might make sense to be a little more explicit about it in the article, just to avoid confusing people like me. ;-)
Jul 22, 2008 at 9:07 AM
I've submitted an update to my article, might take a day or two to show up. I've changed the way the Factory works and it's much cleaner. No more need to check if the object exists in the container, I've simply defined the container in the config file.
I haven't had much feedback on this so if you get a chance to check out the new article once it's posted, that'd be awesome!


Jul 25, 2008 at 1:12 AM
This article has been updated. It is alot clearer and a far better solution:
http://www.codeproject.com/KB/linq/LinqAndUnity.aspx