views:

121

answers:

2

Hello, been searching a lot information about IoC/DI development, but I haven't found much information how to integrate an ORM into the IoC/DI development.

  1. Should the IoC know about the ORM? Or vice versa?
  2. How does the IoC configuration mapping work when mapping a "ORM type"?

Example:

public class Person : IPerson
{
    private IPersonModel _model;

    public Person(IPersonModel model)
    {
        _model = model;
    }
}    

IoC.Register<IPerson>.As<Person>();    
IPerson = IoC.Resolve<IPerson>();   

How does the IoC/ORM work here, IPersonModel can be any person in my data base (or other data store) ?

I feel there must a method or such like this:

IPerson = IcO.Resolve<IPerson>(() => PersonId = 50);

Anyone want to explain more general how to integrate IoC with an ORM?

+4  A: 

Why do you need a Person class and a PersonModel?

I would use an IoC container to resolve the proper repository that returns the correct IPerson.

For instance:

IPersonRepository personRepo = ObjectFactory.GetInstanceOf<IPersonRepository>();
int id = 12;
IPerson person = personRepo.GetBy(id);

All of your ORM logic would be encapsulated in your repository. More on the repository pattern Here

Wix
The method GetBy should resolve like this then: IcO.Resolve<IPerson>() and then set properties or such? Can one combine repository pattern with DI-pattern, is that common usage?
Marcus
You just want the IoC container to get the correct repository. I am assuming whatever type of person that the repository returns will be based off of whatever comes back from the data source. So the repository may return a type of ConcretePerson1 or ConcretePerson2. That what you mean?
Wix
Ah ok, thank you for explanation
Marcus
A: 

ORM have a session (or whatever the name is) to load entities. The session can indeed be injected by a DI framework.

So in your example, with Hibernate you could have something like:

class Service {

    Session session; // could be injected by DI
    ...
    Person p = (Person) session.load( typeof(Person), 50 );
}

The entity mapping in the ORM is independent of the IoC configuration.

Entities in an ORM hold data in the simplest way. You usually don't need to have an interface for your entity.

public class Person 
{    
  Integer id;
  String name;
  // getter and setter for the values
}

The mapping can be done in various way. The idea is that you map the properties in the class to columns in the database. Here would be an excerpt of the configuration with the hibernate.

 <class name="Person" 
    table="PERSON" >     

    <id name="id" column="PERSON_ID">
       <generator class="native"/>
    </id>

    <property name="name" column="NAME" />           
    ...
  </class>

This were just the general ideas (sorry if there are mistakes). The details will depend on the IoC/DI you use, as well as the ORM, of course.

EDIT

Here is what I meant in my comment:

abstract class Person {
   abstract Presenter GetPresenter();
   ...
}

class Person1 : Person { 
  Presenter GetPresenter() { return new PresenterForPerson1() }
  ...
}

// other subclasses

You don't use IoC to load entities, you use the session/repository.

Person person = session.Load( typeof(Person), 50 );

ORM support polymoprhic entities. So the person object that is loaded can have concrete type Person1, Person2 etc.

To obtain the presenter for the person, you use

Presenter presenter = person.GetPresenter();

That's plain OO.

For testing, you could subclass PersonX with PersonXTest and override GetPresenter to return mock presenter. Then you change the config of the ORM to user PersonXTest instead of PersonX for testing. No need of DI then.

ewernli
Difficult to explain this but lets say I have a PersonPresenter which depends on IPersonModel (which is a ORM-entity), how can I in my code resolve a PersonPresenter with a certain person-entity?IoC.Resolve<IPersonPresenter>() <-- ?
Marcus
Not sure I understand what you mean. But if you can have different concrete Person types, and there is a presenter for each one, the easiest way is to add `getPresenter()` in each Person class which returns the right presenter to use. No need of DI in this case, plain OO / polymorphism should work.
ewernli
What I mean is that in these cases you can't use IoC.Resolve<IPersonPresenter>(), because the person presenter depends on a person model which in turn is a orm entity. Somewhere I must specify which Id or such I want for the person model (orm entity).So rather than IoC.Resolve<IPersonPresenter>(), I should use IoC.Resolve<IPerson>().GetPresenter(id: 50) am I thinking right here?
Marcus
I refined my answer based on my previous comment.
ewernli
Ok thats clearify things alot. So general spaking you have to use 2 different configurations (IoC + ORM), I was under the impression that one could "merge" in the ORM into the IoC somehow and only needing IoC-configuration.
Marcus
I doubt it's possible. If you figure out how to do that, let me know :)
ewernli