2010-07-14 11 views
4

J'ai une application Silverlight 4 pour une simple liste 'TODO'. Le problème que j'ai est que la liaison de données est l'accrochage des relations sur mon objet TODO, ce qui provoque le contexte de données RIA pour l'ajouter à la liste DataContext.TODOs avant que je le veux là. Je souhaite traiter l'objet comme nouveau et détaché jusqu'à ce que je sois explicitement prêt à l'ajouter au contexte de données.Comment empêcher Silverlight RIA Entity d'être attaché au datacontext avant que je sois prêt


Voilà comment cela fonctionne: J'ai mon entité TODO qui est associée à une (relation d'entité de services RIA) Status.

Je crée une nouvelle entité TODO() qui est transmise à une fenêtre contextuelle ChildWindow. Notez que je n'ajoute pas cette nouvelle entité à mon datacontext.

new CreateTODOPopup(new TODO()).Show(); 

Dans le DataForm dans mon ChildWindow J'ai un combobox pour Status qui est DataBound à DataContext.Statuses.

Le problème est que l'action de la sélection d'un Status dans la liste déroulante associe effectivement l'entité au contexte pour moi - finissant par donner un état de EntityState.New et fait ajouter à la DataContext.TODOs colleciton.

Ce serait bien, sauf qu'il apparaît maintenant dans la liste principale TODO dans le cadre principal. Je ne veux pas que ce soit parce qu'il n'a pas encore été commis par ChildWindow.

Comment puis-je résoudre ce problème? Soit en empêchant l'entité de devenir attachée - soit en la cachant d'une manière ou d'une autre à tout contrôle auquel elle est liée jusqu'à ce qu'elle ait été ajoutée.

Répondre

0

Avez-vous essayé d'utiliser Context.Detach sur l'objet afin de spécifier clairement qu'il ne doit pas être dans le contexte? Ensuite, vous pouvez Context.Attachez-le à nouveau avant de l'enregistrer.

+1

Je ne l'attache jamais explicitement, il se fixe simplement. Je ne suis pas sûr quand je le détacherais –

1

Vous devriez pouvoir obtenir le comportement souhaité en ajoutant une autre propriété 'MyProject' à l'entité TODO en utilisant une classe partielle. Dans votre popup, vous pouvez définir la propriété 'MyProject' au lieu de la propriété 'Project'. Lorsque vous enregistrez votre TODO, vous pouvez ensuite appliquer la valeur 'MyProject' directement à 'Project'. Un peu détourné, mais il devrait vous donner le comportement que vous souhaitez.

Kyle

+0

+1 pour sournois. certainement pas évolutif mais intéressant une pensée –

+0

Une autre approche pourrait être de créer l'association en utilisant StatusId au lieu de Status. J'ai vu différents comportements des deux approches. –

1

Je suppose que d'une façon serait d'utiliser un PagedCollectionView et filtrer les entités « nouvelles » - mais il doit être quelque chose évidente que vous êtes absent.

// data bind list to this ICollectionView 
    private PagedCollectionView _projects; 
    public PagedCollectionView Projects 
    { 
     get 
     { 
      if (_projects == null) 
      { 
       _projects = new PagedCollectionView(_todoDomainContext.TODOProjects) 
       { 
        Filter = i => { 

         DM.TODOProject proj = (DM.TODOProject)i; 

         // hide New entities 
         if (proj.EntityState == EntityState.New) 
         { 
          return false; 
         } 

         return true; 
        } 
       }; 
      } 
      return _projects; 
     } 
    } 
+2

oups. j'ai écrit ceci à la troisième personne ... à moi-même ...: - / –

1

IMPORTANT: Après 3 jours de lutte avec une condition de type course terrible, il se sont avérés être directement liés à ce problème. Fondamentalement, la conclusion est - si vous essayez de créer des entités et ne pas les ajouter au contexte de données, puis ne pas si vous ne voulez pas les conditions de course et un comportement inattendu. Je suis sûr que c'est un bug de services RIA.

Ce que je faisais:

  • Création d'un new TODO() et le transmettre à mon avis
  • autorise les services de RIA cadre pour associer mon TODO avec toutes les tables de clés étrangères, telles que Status et AssignedTo
  • Sur 'enregistrer', ajouter le TODO() à la liste s'il n'était pas déjà présent dans le jeu d'entités DataContext.TODOs.

Ce que le cadre a fait par lui-même:

  • Lorsque la vue fixe les clés étrangères sur l'objet (via un comobox), il ajoute automatiquement le TODO à la collecte DataContext.TODOS. C'est juste la façon dont les entités fonctionnent.

Pourquoi est-ce mauvais:

  • Lorsque vous naviguez autour de mon interface utilisateur une condition de course terrible se produisait.
  • Les lignes préexistantes (même celles qui existaient avant le démarrage de mon application) étaient marquées New - parfois jusqu'à 20 d'entre elles, puis réenregistrées en tant que nouvelles lignes dupliquées.

Comment je l'ai fixé:

  • Toujours ajouter des entités créées dans le contexte de données immédiatement sur la création.

Voici quelques exemples de code pour ajouter des entités immédiatement sur la création - aucune condition de course:

for (int i = 0; i < 3; i++) 
{ 
    var entity = new DM.TODO(); 
    _todoDomainContext.TODOs.Add(entity); 

    entity.TODOStatu = pendingStatus; 
    entity.TODOProject = project; 
    entity.TODOCompany = company; 

    entity.CreateDt = DateTime.Now; 

    entity.Title = "generated todo " + DateTime.Now.ToString(); 
    entity.Details = "12345"; 
} 

Ce code ne fonctionnait pas, et provoque des conditions de course - l'ajout d'entités après clés étrangères ont déjà été mis en :

for (int i = 0; i < 3; i++) 
{ 
    var entity = new DM.TODO(); 

    entity.TODOStatu = pendingStatus; 
    entity.TODOProject = project; 
    entity.TODOCompany = company; 

    entity.CreateDt = DateTime.Now; 

    entity.Title = "generated todo " + DateTime.Now.ToString(); 
    entity.Details = "12345"; 

    _todoDomainContext.TODOs.Add(entity); 
}