views:

132

answers:

3

Hi!

I am using NHibernate and have a many-to-many association between an Employee and a Team.

Now I want to display all Employees with the name of its Team member.

Possibility 1:

  • using AutoMapper and create a DTO containing the Employee properties and the name of the Team (eager load the Team)
  • display the DTO in the view

Possibility 2:

  • create a new Entity called EmployeeTeam and map it with NHibernate/FluentNHibernate (this entity acts as the relational table between the Employee and Team in the database)
  • load TeamEmployee by using eager loading include Employee and Team
  • display the EmployeeTeam entity
  • use the EmployeeTeam members (EmployeeTeam.Employee.Name, EmployeeTeam.Team.Name)

Possibility 3:

  • as possibilities 1 and 2
  • using a DTO for the EmployeeTeam

Possibility 4:

  • use ICriteria API
  • use the AliasToBeanResultTransformer (didn't use this)

Possibility 5:

  • use LINQ to NHibernate
  • I think I will still need the EmployeeTeam Entity (which is for now not in my Domain Model)

What is the best practices for this problem?

Any other suggestions?

A: 

It depends if you want to use DTOs stictly to separate your business logic from your presentation logic (architectural decision). In a such scenario I would prefer solution 1.

If you have behaviour for an entity like EmployeeTeam or there will be a reuse (for example in a report), then I would prefer solution 2.

p2u
EmployeeTeam does not exist in the domain model.
Rookian
A: 

create a view dto with the fields you want to display as properties. using automapper - map the entity properties to your new dto:

Mapper.CreateMap<Obj1, NewObjDto>()
                .ForMember(dest => dest.Prop1, opt => opt.MapFrom(src => src.Obj1.Prop1));

in other words - your view dto doesn't have to resemble your domain objects.

w://

cvista
this is the approach I use now, but I ask myself if that is really necessary.
Rookian
+2  A: 

This sounds like a UI nightmare, but you could just pass your list of employees to the view. Then have a nested loop that loops through the Teams within a loop that loops through the employees. It would look something like this in Asp.Net MVC -

<table>
    <thead>
        <tr>
            <td>Employee</td>
            <td>Team</td>
        </tr>
    </thead>
    <% foreach(var employee in Model.Employees) { %>
        <% foreach (var team in employee.Teams) { %>
            <tr>
                <td><%=employee.Name %></td>
                <td><%=team.Name %></td>
            </tr>
        <% } %>
    <% } %>
</table>

You would use a ViewModel (DTO) in the following circumstances -

  • if the domain model is very complex and simplifying helps readability
  • if you need to do some view data modifications before display
  • if you need to update values on postback.

I'd avoid option two as it just adds unneccesary complexity (from what I can deduce from the current info provided) to your domain :-)

Update

If you'd like an employee with no teams to still be displayed you could set this in the view...

<table>
    <thead>
        <tr>
            <td>Employee</td>
            <td>Team</td>
        </tr>
    </thead>
    <% foreach(var employee in Model.Employees) { %>
        <tr>
            <% if (employee.Teams.Any()) { %>
                <td><%=employee.Name %></td>
                <td> - </td>
            <% } else { %>
                <% foreach (var team in employee.Teams) { %>
                    <td><%=employee.Name %></td>
                    <td><%=team.Name %></td>
                <% } %>
            <% } %>
        </tr>
    <% } %>
</table>

Obviously the more UI tweaks like this that exist the more likely you are to want to use a ViewModel to clean up your View. If you find that your view is starting to become unreadable due to the number of inline code references then this is usually an indication that a ViewModel (DTO) would be applicable :-)

Russell Giddings
Your view looks like my first approach. The problem there was that when an Employee has no Teams the second foreach loop is not executed and because of this the Employee is not displayed.
Rookian
I've added an update to my answer which should help fix the issue of an employee with no team.
Russell Giddings
You may want to also wrap the whole table with an if statement that queries to check that there are any employees that belong to teams... Model.Employees.Where(e => e.Teams.Any()).Any()
Russell Giddings
I read that logic in a view is bad :o because of seperation of concerns ... I had this idea too but ya it is not the clean way =)
Rookian
Business logic in a view is bad. This is not business logic though, this is display code. You are taking an object that contains data that you want to display and displaying that data in a certain way. So the problem is not about "logic" being in the view, but more about the view being readable. It can get to the stage where too much display manipulation in code within the view can make the view confusing. In which case a ViewModel would simplify things. This is especially true when you have a team with a front end developer that will be modifying the view who doesn't fully understand C#
Russell Giddings
I wouldn't call it "logic" as much as formatting. The best place for that sort of thing is in the view, IMO.
Mark Worth