views:

285

answers:

2

Hi, All

When I run following code:

public ActionResult Complete()
        {
            try
            {
                VeriTabanDataContext db = new VeriTabanDataContext();
                db.Persons.InsertOnSubmit(_person);
                db.SubmitChanges();
                return View(_person);
            }
            catch (Exception ex)
            {
                return RedirectToAction("Error", ex);
            }
        }

I'm getting following Exception, on SubmitChanges();

"An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported."
  • Here "_person" object is taken from Session and is a good standing. Note: _person is a result of multistep wizard and this is the place where I add new Person object to the DB.
  • My Person table has 9 relations and it's not ok for me to add version column for each of them as is suggested by some geeks around
  • I've investigated this problem a lot and spend 2 days on it and still couldn't solve it. Some of the workarounds that other suggest don't solve my problem, and others seem to be just dirty workaround. Do you experts have a good solution for this problem, considering that Person class has many relations and also it isn't ok to add a column to the tables.
  • I also want to note that I've tried to use 'db.Persons.Attach(_person) ' and setting db.DeferredLoadingEnabled = false; THis time I'm not getting any Exception but data is NOT saved to DB
+1  A: 

Can you do the following:

var foundPerson = db.Person.FirstOrDefault( p => p.Id == _person.Id);

if(foundPerson == null)
{
  db.InsertOnSubmit(_person);
}else{
  Mapper.Map(_person,foundPerson);
}

db.SubmitChanges();
return View(_person);

Where I have used AutoMapper to map from one entity to another. To do this add the reference to AutoMapper to your project and in your start up code for the application you will need to configure your mappings, for the above to work you would need:

Mapper.CreateMap<Person, Person>().ForMember(src => src.Id, opt => opt.Ignore());
bobwah
`foundPerson.Name = _person.Name` will not work for me, because this way I'll have to copy more than 30 fields. Also if count dependent childe objects then I'll have to do this kind of assignment for more than 100 fields. So this solution is not acceptable unless there is easier way to update `foundPerson`. Thanks for answer.
Azho KG
updated to use AutoMapper
bobwah
+1  A: 

I create a class called applicationController which derives from Controller. Then i make all of my controller classes derive from this. The applicationController class has a constrcutor which creates a new instance of my repository (or datacontext in your instance) which is used throughout the application:

     public class ApplicationController : Controller
     {
          private VeriTabanDataContext _datacontext;

          public ApplicationController() : this(new VeriTabanDataContext())
          {
          }

          public ApplicationController(VeriTabanDataContext datacontext)
          {
               _datacontext = datacontext;
          }

          Public VeriTabanDataContext DataContext
          {
               get { return _datacontext; } 
          }
     }

Then you can use this in all of your controllers

public class MyController : ApplicationController
{
     public ActionResult Complete()        
     {            
           DataContext.Persons.InsertOnSubmit(_person);              
           DataContext.SubmitChanges();                
           return View(_person);            
     }
}

Not on my PC with VS installed at the moment so not tested this code....

Hope this resolves the issue -Mark

Mark
I've not tried it yet, but this would solve the problem if my object was taken from on context and being tried to be inserted in another context. But my object is newly created and is not tracked by any context yet. So I suspect this will not work. I just wanted so say my opinion before trying it and try later if my thinking is proved to be wrong.
Azho KG
should work as you will only have one instance of the datacontext where at the moment it looks like you are creating multiple instances within each controller action.
Mark
This solved my problem. Thanks.
Azho KG