views:

244

answers:

2

I have this test in my test base:

public void WorksWithAreaUsers()
     {
      using (new TransactionScope())
      {
       //arrange
       var userBusiness = new UserBusiness();
       var user = new User
       {
        Name = "TestUser###",
        Login = "domain\test-user###"
       };
       userBusiness.Add(user);

       var areaBusiness = new AreaBusiness();
       var area = new Area
       {
        Name = "TestArea###",
        Description = "Test Area Description",
        Users = new List<User> { user }
       };

       //act
       areaBusiness.Add(area);

       //assert
       var areaFromDb = areaBusiness.FindById(area.AreaID);
       Assert.IsNotNull(areaFromDb.Users);
       Assert.IsTrue(areaFromDb.Users.Count > 0);
       Assert.IsTrue(areaFromDb.Users.Any(c => c.UserID == user.UserID));
      }
     }

What it is doing:

  • Inserts a new user into the base;
  • Inserts a new area into the base, with the user relationship;

What actually happens:

  • The new user is inserted;
  • The new area is inserted;
  • The new user is inserted again, with area relationship;

What can be happening?

More information:

  • Area and User aren't EntityObjects really. I am mapping DTO/Entity using AutoMapper, I think the problem is in this logic. In a certain moment, I have to map between the List and the EntityCollection. I create a new EntityCollection and put the User converted into a UserEntity in this collection, using the EntityCollection.Add method. I think I should use Attach in order to not create a new entity, but this method doesn't work when called from an EntityCollection without the proper bindings.

Do you suggest anything clever than that, or any workaround to solve this issue? I really need the project layers (Web -> Business -> Data -> EF), asp.net working directly with EF is something we can't do here, for modularity reasons.

EDIT:

I'm giving up the idea of using AutoMapper to do this job =/ I don't have a lot of entities, and the changes I need to do in this library in order to work requires some effort, it isn't something trivial to do. It is better to do the mapping by myself.

A: 

I assume your User object has an Area property that can also be used to establish the relationship between the entities. Instead of setting Area.Users equal to a new list, after you create the area object just set User.Area equal to the new area. This is how I handle associating new entities and it works reliably.

EDIT

If I understand what you are doing, you are creating business objects (BOs) that later create entity objects (EO) and attach those EOs to a context and save them.

Assuming I have the basics correct, determing the exact cause of you problem requires seeing the code for how the respective BOs create EOs and attach them to the context.

RB Davidson
This is a many-to-many relationship. Does it change something?
Victor Rodrigues
In that case, try doing Users.Add(user) or user.Areas.Add(Area) type of logic.
RB Davidson
A: 

My guess (and it is just a guess) is that AutoMapper isn't doing identity resolution

So when it sees the same object (user) in different places in the graph it creates a new object rather than re-using the object it created previously.

This would probably explain what you are seeing.

Alex

Alex James