7
votes

Cadre d'entité contextes d'objet multiple

Cette question a été posée 500 fois différente de 50 façons différentes ... mais ici c'est encore, car je ne peux pas sembler trouver la réponse que je recherche:

J'utilise EF4 avec les proxies POCO .

a. J'ai un graphique d'objets que j'ai récupérés d'une instance d'un objetContext. Cet objetContext est disposé.

b. J'ai un objet que j'ai récupéré d'un autre exemple d'objetContext. Cet objetContext a également été disposé.

Je veux définir une propriété liée sur un tas de choses à partir d'une utilisation de l'entité à B .... quelque chose comme xxx

quand je fais que, je reçois l'exception: xxx

Je suppose que je dois détacher ces entités à partir des objetsContextes lorsqu'ils disposent pour que ce qui précède fonctionne, le problème est, Détacher toutes les entités de mon objetContext lorsqu'il dispose semble détruire le graphique. Si je fais quelque chose comme: xxx

Toutes les relations dans le graphique semblent avoir non défini.

Comment puis-je faire la résolution de ce problème?


0 commentaires

4 Réponses :


3
votes

Je ne pense pas que vous devez vous détacher pour résoudre le problème.

Nous faisons quelque chose comme ceci: xxx

Cela nous permet de tirer les données, passez C'est à une autre couche, laissez-les faire tout ce dont ils ont besoin de faire, puis de le transmettre et de la mettre à jour ou de la supprimer. Nous faisons tout cela avec un contexte distinct (une par méthode) (une par demande).

La chose importante à retenir est, si vous utilisez ienumerables, ils sont Exécution différée. Ce qui signifie qu'ils ne tirent pas réellement les informations avant de faire un compte ou une itération sur eux. Donc, si vous souhaitez l'utiliser en dehors de votre contexte, vous devez faire une toliste () de sorte qu'il soit itéralé sur une liste et une liste est créée. Ensuite, vous pouvez travailler avec cette liste.

Modifier mis à jour pour être plus clair, grâce à l'entrée de @ Nick.


12 commentaires

1. Cela ressemble à votre exemple est avec entitéObjects, non pocos, correct? 2. Je n'ai pas accès au contexte de l'objet directement au point où j'essaie de définir l'entité associée. Je n'ai qu'une entité de contact et une entité de vente et j'essaie de définir la propriété Sale.Seller à l'aide de l'entité de contact. Les contextes d'objet ont depuis longtemps été disposés et sont sortis de portée.


Question mise à jour avec l'erreur que je reçois ... Désolé aurait dû poster cela en premier lieu ...


Vous ne voulez pas vraiment ouvrir un nouveau contexte pour chaque demande. Et puis ouvrez un autre à chaque fois que vous faites une sauvegarde. Cela va tuer la performance, vous souhaitez conserver une unité de travail pour toute votre action. Ou en d'autres termes, ouvrez le contexte effectuez votre travail, puis fermez le contexte.


D'accord ... mais ce cas n'est pas applicable ici. J'ai une collection A à la suite d'un flux de travail complet et d'une transaction commerciale qui a eu lieu. L'entité B est séparée et entre en jeu une fois le flux de travail terminé.


@Nick, notre site Web a une performance sous-seconde sur les perquisitions de milliers (voire des millions) d'enregistrements. La performance avec une approche d'un par appel n'a pas été un problème pour nous.


@Jeff, non, nous utilisons Pocos, code en premier. Qu'en est-il du code ci-dessus causant la confusion?


@Jeff, étant donné l'erreur ci-dessus dans votre mise à jour, cela ne résoudra probablement pas le problème. Je pensais que tu courais dans quelque chose d'autre


Les Pocos n'ont normalement pas une propriété d'entité de l'entité sur eux ... mais non plus l'entitéObjects (ils ont une entité d'entité) ... Donc je ne suis donc pas sûr de ce qui se passe là-bas: contactez.state = entitéstate.modified;


@Taylonr Sous-Second n'est pas vraiment grand. Mon temps de réponse typique est d'environ 200ms. Vous devriez consulter l'EFPROF, cela pourrait vous aider à trouver des problèmes et accélérez votre site.


@Nick, notre site n'a pas besoin de beaucoup d'aide, nous sommes dans cette gamme, je parlais simplement en général lorsque j'ai dit sous-seconde (suppose que j'aurais pu dire la demi-seconde mais qui semblait être une bouchée)


@Taylonr - Eh bien Ayende est un gars très intelligent EFProfrof.com/learn/alerts/MultiplesessionsInthesamerequest


@Nick, maintenant je comprends la confusion ... J'ai dit "une par méthode" qui n'était pas tout à fait vrai, la plupart de nos demandes sont une méthode unique (comme obtenir toutes les responsables des ventes pour Mike, donc dans ces cas, c'est un par La méthode et chaque requête est une méthode.) Dans nos demandes plus compliquées, nous faisons encore 1 par demande ... ça sonne comme moi ne pas être clair fini par nous dire au sein du même côté :) mon mauvais.



5
votes

Je pense que vous avez quelques options différentes ici, 2 d'entre eux sont:

  1. laisser le contexte en vie jusqu'à ce que vous ayez terminé avec le processus, utilisez seulement 1 contexte, pas 2.

  2. a. Avant de disposer du contexte n ° 1, créant un clone profond de graphique, à l'aide de Barylstreamer ou à un outil tel que ValueInjecteur ou automapper .

    b. Fusionner les changements du contexte n ° 2 en graphique cloné.

    c. Lors de la sauvegarde, la fusion des changements de graphique cloné en graphique créé par nouvel objetContext.

    Pour une référence future, ce lien MSDN Blogs peut aider à décider de décider quoi faire quand: http: // blogs .msdn.com / B / DSIMMONS / Archive / 2008/02/17 / Context-Lifetimes-Dispez-Dispez-or-réutilisation.aspx


13 commentaires

Je suis sûr que j'espère que ce n'est pas la réponse.


Pourquoi fermez-vous vos contextes? - Si vous fusionniez des résultats de divers contextes, vous ne travaillez évidemment pas vraiment apatrides. Je soupçonne que beaucoup ne pas gérer correctement le contexte de la vie.


J'ai deux écrans complètement différents dans une application Windows Forms. Parfois, ces deux écrans sont présentés en séquence, initiés par un autre (troisième) écran. Dans ce flux de travail, les entités / entités résultantes de 2 écrans sont utilisées par l'appelant pour effectuer une opération. En conséquence, les présentateurs des deux écrans ont déjà disposé et ont donc l'objet d'objets qu'ils utilisaient.


Les deux écrans fonctionnent-ils sous la même application? Les deux écrans sont-ils présentés au même utilisateur? Vous ne voulez pas voir l'affect des changements d'un écran d'un autre?


Pourquoi votre couche de présentation ouvre-t-elle un objetContext? Vous n'avez pas de couche d'entreprise ou de contrôleur ou de menualité de vue en dessous qui est commun aux différentes vues?


Ce n'est pas le cas. Il y a une couche de services qu'un présentateur parle. Le scénario le plus simple que je puisse expliquer est ceci: l'utilisateur passe par le flux de travail pour créer un nouveau "widget". Widget est enregistré via un appel des services aux entreprises et le présentateur de l'écran "Créer un nouvel widget" renvoie une instance du widget sur le présentateur d'appel (celui qui a surgi la fenêtre "Créer une nouvelle widget"). Un écran avec une combinaison combinée par des entités apparaît. Le présentateur de cet écran renvoie l'entité sélectionnée dans le ComboBox. Le présentateur appelant doit prendre la nouvelle entité de widget et définir la valeur de ComboBox sélectionnée dessus.


Votre application complète partage l'état (qui a du sens, puisqu'il s'agit d'une application de bureau). Pourquoi utilisez-vous SOA STAOA SOA ou SOA en général pour une application de bureau? Pourquoi ne pas utiliser un contexte et avoir vos points de vue sur le même modèle / l'état?


La couche de services peut exécuter en mode distribué (WCF) à l'avenir.


Divisez la couche de service en 2: 1. Une couche BL pouvant être partagée entre bureau et serveur, 2.a. Une couche de services pour le bureau qui (en supposant que l'apatride) s'ouvre et ferme un nouveau contexte à chaque fois. 2.b. Une couche de contrôleur de bureau qui ouvre le contexte et le garde en vie. Calques 2.a./2.b. Utilisez la couche 1. La couche 1. est donnée au contexte (ne le gère pas).


Cela semble plus semblable à ce que la mise en œuvre de Microsoft Microsoft mal pensée, à moitié cuit au repos que de développer une solution bien architecturée.


En fait, une «solution bien architecturée» doit correspondre au domaine du problème. Le vôtre est une application de bureau, pas un service Web apatride.


L'ensemble du processus que vous avez décrit la scission de la couche de services n'est nécessaire que grâce à une mauvaise mise en œuvre / architecture dans le cadre d'entité. Dès avoir à contorter l'architecture de votre logiciel pour adresser des défauts fondamentaux dans le cadre que vous le construisez à nuire à la manière dont votre logiciel "bien architecturé" est. Pour dire que le problème ici est l'état d'état-physique et l'apatridie est de négliger le fait que la seule raison pour laquelle il s'agit d'un problème est dû à EF.


Je conseillerais de manière à utiliser exactement la même application (moins la couche de présentation) pour une application de bureau d'état et un service Web alternatif multi-utilisateur, car ils ne sont pas destinés à agir de la même manière. Blaming EF ne vous aidera pas :-) Même avec un service Web d'état, je vous recommanderais de réviser l'architecture.



13
votes

@danny varod a raison. Vous devez utiliser un objetContext pour l'ensemble du flux de travail. De plus, comme votre flux de travail semble être une caractéristique logique contenant plusieurs fenêtres, il devrait probablement également utiliser un seul présentateur unique. Ensuite, vous suivriez l'approche recommandée: contexte unique par présentateur. Vous pouvez appeler SAVECHANGES plusieurs fois, de sorte qu'il ne doit pas casser votre logique.

La source de ce problème est un problème bien connu avec la carence des proxies dynamiques générées sur des entités de POCO combinées à des méthodes de fixation générées par Modèle Poco T4. Ces procurations sont toujours en référence au contexte lorsque vous le disposez. À cause de cela, ils pensent qu'ils sont toujours attachés au contexte et qu'ils ne peuvent pas être attachés à un autre contexte. La seule façon de les forcer à libérer la référence au contexte est le détachement manuel. Dans le même temps une fois que vous détachez une entité du contexte, il est supprimé des entités jointes connexes car vous ne pouvez pas avoir de mélange d'entités attachées et détachées dans le même graphique.

Le problème ne se produit pas dans la code que vous appelez: xxx

mais dans l'opération inverse déclenchée par méthode de fixuption: xxx

Je pense que les façons de résoudre Ceci sont:

  • Ne faites pas cela et utilisez un seul contexte pour une unité de travail entière - c'est la supposée usage.
  • Supprimer la propriété de navigation inverse de sorte que la méthode de fixupture ne déclenche pas ce code.
  • N'utilisez pas de modèle POCO T4 avec des méthodes de fixuption ou modifiez le modèle T4 pour ne pas les générer.
  • Éteignez la chargement paresseux et la création de proxy pour ces opérations. Cela éliminera les proxy dynamiques de votre POCOS et à cause de cela, ils seront indépendants dans le contexte.

    Pour désactiver la création proxy et la chargement paresseuse Utilisation: xxx

    Vous pouvez réellement essayer d'écrire une méthode personnalisée pour détacher tout le graphique de l'objet, mais comme vous l'avez dit. On a demandé 500 fois et je n'ai pas encore vu de solution de travail - sauf la sérialisation et la désérialisation au nouveau graphique d'objet.


0 commentaires

0
votes

OK, je comprends que votre contexte d'objet a longtemps disparu.

Mais regardons cela de cette façon, l'entité cadre implémente une unité de concept de travail, dans laquelle il suit les modifications que vous apportez dans votre graphique de votre objet afin de générer le SQL correspondant aux modifications que vous avez apportées. Sans attaché au contexte, il n'ya aucun moyen de passer des changements d'exploitation.

Si vous n'avez aucun contrôle sur le contexte, je ne pense pas que vous puissiez faire quelque chose.

sinon il y a deux options,

  1. Gardez le contexte de votre objet vivant pour une durée de vie plus longue, comme la session de l'utilisateur connecté, etc.
  2. Essayez de régénérer vos classes de proxy à l'aide de modèles de texte de suivi automatique permettant de modifier le suivi dans l'état déconnecté.

    Mais même en cas de suivi de soi, vous pouvez toujours avoir peu de problèmes.


0 commentaires