2009-03-29 1 views
19

Я пытаюсь сохранить мой контакт, в котором есть ссылки на ContactRelation (только отношения контакта, замужних, одиночных и т. Д.) И страны. Но каждый раз, когда я пытаюсь сохранить мой контакт, который проверенный я получаю исключение «ADO.Net Entity Framework Объект объекта не может ссылаться несколько экземплярами IEntityChangeTracker»ADO.Net Entity Framework Объект сущности не может ссылаться на несколько экземпляров IEntityChangeTracker

public Contact CreateContact(Contact contact) 
{ 
    _entities.AddToContact(contact); //throws the exception 
    _entities.SaveChanges(); 
    return contact ; 
} 

я использую слабосвязанной MVC дизайн с услугами и репозиториями. Я прочитал много сообщений об этом исключении, но тем не дать мне рабочий ответ ...

Спасибо, Петр

ответ

21

[Update]
Поскольку L2E используется вам необходимо сохранить все связанные объекты, прежде чем вы можете сохранить основной объект. Что имеет смысл, иначе вы бы создали (в моем примере) художника без его контактного объекта. Это не допускается дизайном базы данных.
[/ Update]

Вот моя реализация, которая сработала.

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude = "Id")] Artist artist, [Bind(Prefix = "Contact")] Contact contact, [Bind(Prefix = "Country")] Country country, [Bind(Prefix = "ContactRelationship")] ContactRelationship contactRelationship) 
{ 
    ViewData["Countries"] = new SelectList(new CountryService(_msw).ListCountries().OrderBy(c => c.Name), "ID", "Name"); 
    ViewData["ContactRelationships"] = new SelectList(new ContactRelationshipService(_msw).ListContactRelationships().OrderBy(c => c.ID), "ID", "Description"); 

    country = _countryService.GetCountryById(country.ID); 
    contact.Country = country; 
    contactRelationship = _contactRelationshipService.GetContactRelationship(contactRelationship.ID); 
    contact.ContactRelationship = contactRelationship; 
    if(_contactService.CreateContact(contact)){ 
     artist.Contact = contact; 
     if (_service.CreateArtist(artist)) 
      return RedirectToAction("Index");   
    } 
    return View("Create"); 
} 

А потом в моей ContactRepository:

public Contact CreateContact(Contact contact) 
{ 
    _entities.AddToContact(contact); //no longer throws the exception 
    _entities.SaveChanges(); 
    return contact ; 
} 

Я также нашел на этом сайте, что лучше всего, чтобы сохранить тот же контекст, на протяжении всего приложения, так что я теперь использует специальный класс данных для это:

Rick Strahl и Samuel Maecham научили меня, что вы должны хранить свой datacontext для каждого пользователя за запрос. Это означает, что он помещается в HttpContext для веб-приложений. Читайте об этом here

public class Data 
{ 
    public static MyDBEntities MyDBEntities 
    { 
     get 
     { 
      if (HttpContext.Current != null && HttpContext.Current["myDBEntities"] == null) 
      { 
       HttpContext.Current["myDBEntities"] = new MyDBEntities(); 
      } 
      return HttpContext.Current["myDBEntities"] as MyDBEntities; 
     } 
     set { 
      if(HttpContext.Current != null) 
       HttpContext.Current["myDBEntities"] = value; 
     } 
    } 
} 
+1

Спасибо, Питер, я трачу около часа, пытаясь найти то же самое решение. Еще раз спасибо – Geo

5

Я видел это раньше, возможно, придется конвертировать в справочном поле до EntityKey перед сохранением, а затем загрузить его после сохранения. Попробуйте этот код вместо:

public Contact CreateContact(Contact contact){ 
    contact.ConvertContactRelationToReference(); 
    _entities.AddToContact(contact); 
    //throws the exception 
    _entities.SaveChanges(); 
    contact.ContactRelation.Load(); 
    return contact; 
} 

public partial class Contact 
{ 
    public void ConvertContactRelationToReference() 
    { 
    var crId = ContactRelation.Id; 
    ContactRelation = null; 
    ContactRelationReference.EntityKey = new EntityKey("MyEntities.ContactRelations", "Id", crId); 
    } 
} 

Конечно, некоторые из этого кода, возможно, потребуется изменить в зависимости от конкретной структуры базы данных.

+0

Благодарим вас за то, что указали мне в правильном направлении, вы в порядке, если я задал свой ответ в качестве принятого ответа? – Peter

+0

Если я помогу, вы можете меня опротестовать. Вы можете пометить себя как выбранный ответ, но вы не получите за него никакой репутации. – bendewey

+0

Буду как только у меня хватит репутации, спасибо! – Peter

2

Ummm Интересно, если кто-то может понравиться здравомыслие проверить мое решение. Это очень похоже на принятый ответ ниже, но после прочтения блога Рика Страйла о DataContext Life Management Я волнуюсь, что это не потоковое решение для веб-приложения.

Я также получил экземпляр экземпляра, где я получил это сообщение об ошибке, обратившись к объекту, используя одноэлементный шаблон.

Я добавил следующее MyObjectContext класс:

// singleton 
private static MyObjectContext context; 
public static MyObjectContext getInstance() 
{ 
    if (context == null) 
    { 
     context = new MyObjectContext(); 
    } 
    return context; 
} 

И в моем каждого объекта хранилища картографа вместо инстанцировании новый экземпляр MyObjectContext я использую

var db = MyObjectContext.getInstance(); 

ли я глупа здесь? Кажется, это работает.

+1

Вы не ошибаетесь, singleton DataContext в моем ответе плохой дизайн. Вы должны сделать singleton DataContext, но для каждого пользователя за запрос. т. е. вы должны поместить его в HttpContext для веб-приложения. см. это сообщение: http://samscode.com/index.php/2009/12/making-entity-framework-v1-work-part-1-datacontext-lifetime-management/ – Peter

+0

фантастический, спасибо – user427875

Смежные вопросы

 Смежные вопросы