2008-10-01 5 views
14

Je suis très nouveau dans le cadre de l'entité, alors s'il vous plaît garder avec moi ...Comment associer des objets à partir de plusieurs contextes en utilisant Entity Framework

Comment puis-je relier deux objets de différents contextes ensemble?

L'exemple ci-dessous génère l'exception suivante:

System.InvalidOperationException: La relation entre les deux objets ne peuvent pas être définis parce qu'ils sont attachés à différents ObjectContext objets.

void MyFunction() 
{ 
    using (TCPSEntities model = new TCPSEntities()) 
    { 
     EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123); 
     er.Roles = GetDefaultRole(); 
     model.SaveChanges(); 
    } 
} 

private static Roles GetDefaultRole() 
{ 
    Roles r = null; 
    using (TCPSEntities model = new TCPSEntities()) 
    { 
     r = model.Roles.First(p => p.RoleId == 1); 
    } 
    return r; 
} 

L'utilisation d'un contexte n'est pas une option parce que nous utilisons l'EF dans une application ASP.NET.

+0

Pourquoi avez-vous le nom de votre type de données contexte 'TCPSEntities', et pourquoi avez-vous le nom de votre objet de données contexte' model'? Et vous pourriez penser à ne pas utiliser 'new', mais soit en passant un contexte de données pré-construit ou une fabrique de contexte de données à la fonction. Vous pourriez également penser à utiliser 'Enumerable.SingleOrDefault' au lieu de' Enumerable.First'. – yfeldblum

Répondre

11

Vous devrez utiliser le même contexte (vous pouvez passer le contexte à la méthode getdefaultrole) ou repenser les relations et étendre l'entité.

EDIT: Voulant ajouter ceci pour l'exemple fourni, utiliser asp.net vous demandera de bien réfléchir à vos conceptions de contexte et de relation.

Vous pouvez tout simplement passer le contexte .. IE:

void MyFunction() 
{ 
    using (TCPSEntities model = new TCPSEntities()) 
    { 
     EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123); 
     er.Roles = GetDefaultRole(model); 
     model.SaveChanges(); 
    } 

} 

private static Roles GetDefaultRole(TCPSEntities model) 
{ 
    Roles r = null; 
    r = model.Roles.First(p => p.RoleId == 1); 
    return r; 
} 
2

Yep - travailler sur 2 ou plusieurs contextes ne sont pas pris en charge dans V1 de Entity Framework.

Juste au cas où vous n'avez pas déjà trouvé, il y a une bonne FAQ sur EF à http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx

+1

Ancien poste mais bon lien de référence ... il est maintenant maintenu à http://www.ef-faq.org. – Craig

+0

Faites ce http: //social.technet.microsoft.com/wiki/contents/articles/entity-framework-faq.aspx maintenant. – Kit

2

D'après ce que je comprends, vous voulez instancier votre modèle (via le bit « nouveaux XXXXEntities() ») aussi rarement que possible. Selon MS (http://msdn.microsoft.com/en-us/library/cc853327.aspx), c'est une performance assez importante. L'envelopper dans une structure using() n'est donc pas une bonne idée. Ce que je l'ai fait dans mes projets est d'y accéder par une méthode statique qui fournit toujours la même instance du contexte:

private static PledgeManagerEntities pledgesEntities; 
    public static PledgeManagerEntities PledgeManagerEntities 
    { 
     get 
     { 
      if (pledgesEntities == null) 
      { 
       pledgesEntities = new PledgeManagerEntities(); 
      } 
      return pledgesEntities; 
     } 
     set { pledgesEntities = value; } 
    } 

Et puis-je le récupérer comme ceci:

private PledgeManagerEntities entities = Data.PledgeManagerEntities; 
+0

Ceci est appelé le motif Singleton. –

+1

Un certain nombre de choses: (1) Je pensais que vous deviez faire attention à cela en raison de la manière dont le contexte suivrait les entités qu'il a chargées, ce qui a fait grandir l'instance. (2) L'article que vous référence indique également: "Dans la plupart des cas, vous devez créer une instance ObjectContext dans une instruction using". (3) Si un appel à SaveChanges() échoue, tous les suivants risquent d'échouer sauf si vous détachez les entités défaillantes. Si vous avez plusieurs appelants utilisant le même contexte, vous risquez de vous retrouver dans un pétrin. (4) ObjectContext n'est pas threadsafe –

+0

Ceci est absolument dangereux pour les applications Web et le gain de performance est négligeable. Sauf cas particulier, vous devez généralement utiliser un contexte par opération commerciale. Cela signifie généralement utiliser un contexte par page/fenêtre. – Monstieur

3

Une autre approche que vous pouvez utiliser ici est de détacher des objets d'un contexte, puis de les attacher à un autre contexte. C'est un peu un hack, et cela peut ne pas fonctionner dans votre situation, mais ce pourrait être une option.

public void GuestUserTest() 
    { 
     SlideLincEntities ctx1 = new SlideLincEntities(); 
     GuestUser user = GuestUser.CreateGuestUser(); 
     user.UserName = "Something"; 
     ctx1.AddToUser(user); 
     ctx1.SaveChanges(); 

     SlideLincEntities ctx2 = new SlideLincEntities(); 
     ctx1.Detach(user); 
     user.UserName = "Something Else"; 
     ctx2.Attach(user); 
     ctx2.SaveChanges(); 
    } 
0

Il est l'un des my post, je recherche quelques jours pour rendre cette méthode possible.

Donnez-moi votre feed-back, mais je pense que cela pourrait vous aider à mettre à jour votre EntityCollection

Questions connexes