c # travailler avec Entity Framework sur un serveur multi-threadé

Quelle est la meilleure pratique pour travailler avec un framework d’entités sur un serveur multi-thread? J’utilise ObjectContext Framework d’entité pour gérer toutes mes actions de firebase database, maintenant je sais que ce contexte n’est pas thread-safe, donc pour le moment je dois l’utiliser pour effectuer des actions db. Est-ce que c’est comme ça que je devrais le faire ??

Quelques conseils rapides pour Entity Framework dans un environnement multithread:

  • N’utilisez pas un contexte unique avec des locks (pas de motif singleton)
  • Fournir des services sans état (vous devez instancier et éliminer un contexte par requête )
  • Raccourcissez le plus possible la durée de vie du contexte
  • Mettre en œuvre un système de contrôle de la concurrence . La simultanéité optimiste peut être facilement implémentée avec Entity Framework ( How-to ). Cela garantira que vous n’écrasez pas les modifications dans la firebase database lorsque vous utilisez une entité qui n’est pas à jour

Je suis un peu confus, je pensais que l’utilisation d’un seul contexte est une bonne chose parce que je crois que cela peut être intéressant, alors quand je traite avec la même entité dans des requêtes consécutives, il est beaucoup plus rapide d’utiliser le même contexte. à chaque fois. Alors, pourquoi est-il bon de l’utiliser comme ça s’il est plus lent et toujours pas sûr?

Vous ne pouvez utiliser qu’un seul contexte, mais il est fortement déconseillé, sauf si vous savez vraiment ce que vous faites .

Je vois deux problèmes principaux qui se produisent souvent avec une telle approche:

  1. Vous utiliserez beaucoup de mémoire car votre contexte ne sera jamais éliminé et toutes les entités manipulées seront mises en mémoire cache (chaque entité qui apparaît dans le résultat d’une requête est mise en cache).

  2. Si vous modifiez vos données à partir d’un autre programme / contexte, vous rencontrerez de nombreux problèmes de concurrence. Par exemple, si vous modifiez quelque chose directement dans votre firebase database et que l’entité associée a déjà été mise en cache dans votre object de contexte unique, votre contexte ne connaîtra jamais la modification effectuée directement dans la firebase database. Vous travaillerez avec une entité mise en cache qui n’est pas à jour et croyez-moi, cela conduira à des problèmes difficiles à résoudre.

Ne vous souciez pas non plus des performances de l’utilisation de plusieurs contextes : la création / élimination d’un nouveau contexte par requête est pratiquement insignifiante dans 90% des cas d’utilisation. N’oubliez pas que la création d’un nouveau contexte ne crée pas nécessairement une nouvelle connexion à la firebase database (car la firebase database utilise généralement un pool de connexions).

Est-ce que c’est comme ça que je devrais le faire ??

Non. Au minimum, utilisez un contexte par fil de discussion mais je vous encourage fortement à considérer un contexte comme une unité de travail et à utiliser ainsi un contexte par unité de travail par fil.

A vous de définir “unité de travail” pour votre application. Mais n’utilisez pas le lock pour utiliser un contexte sur plusieurs threads. Il ne s’adapte pas

Vous traitez ObjectContext comme s’il s’agissait d’une entité extrêmement coûteuse, vous l’instanciez une fois et vous le traitez ensuite comme une “façade”. Il n’y a pas besoin de le faire. Si, pour aucune autre raison, les connexions sont regroupées sous le capot et coûtent très peu (microseconde? Probablement moins?) Pour configurer complètement la “chaîne d’objects” pour utiliser l’abstraction ObjectContext.

Le ObjectContext, tout comme l’utilisation directe de SqlConnection, etc., est conçu pour être utilisé avec une méthode d’instanciation aussi tardive que possible et de vidage le plus rapidement possible.

EF vous offre une certaine sécurité dans la mesure où vous avez la possibilité de tester si vous avez les derniers objects avant de les valider (Concurrence Optimiste). Cela ne signifie pas “thread safe” en soi, mais cela se passe de la même manière si vous respectez les règles.

En règle générale, ObjectContext ne doit pas être utilisé globalement dans toute l’application. Vous devez créer fréquemment de nouveaux ObjectContexts et en éliminer les anciens. Ils ne sont certainement pas sûrs non plus. Si vous continuez à utiliser le même ObjectContext (en fonction de la durée de vie de votre application), il est facile d’obtenir une exception de mémoire insuffisante si vous modifiez des quantités massives de données car les références aux entités modifiées sont détenues par le contexte de l’object.

Je crée un nouveau contexte pour chaque opération atomique et dispose du contexte. Autant que je sache des livres et des articles, je préfère garder la durée de vie du contexte aussi courte que possible. (mais cela dépend de votre approche et de votre type d’application, winform ou web)

S’il vous plaît trouver plus d’informations à bon article. http://www.west-wind.com/weblog/posts/2008/Feb/05/Linq-to-SQL-DataContext-Lifetime-Management

Bons livres: http://books.google.co.th/books?id=Io7hHlVN3qQC&pg=PA580&lpg=PA580&dq=DbContext+lifetime+for+desktop+application&source=bl&ots=ogCOomQwEE&sig=At3G1Y6AbbJH7OHxgm-ZvJo0Yt8&hl=th&ei=rSlzTrjAIovOrQeD2LCuCg&sa=X&oi=book_result&ct = result & resnum = 2 & ved = 0CCgQ6AEwAQ # v = onepage & q & f = false

Discussion existante à Datacontext Lifetime dans le scénario de liaison WinForm

J’utilise un framework d’entités dans un environnement multithread, où n’importe quel thread, interface utilisateur et arrière-plan (STA et MTA) peuvent simultanément mettre à jour la même firebase database. J’ai résolu ce problème en recréant la connexion d’entité à partir de zéro au début de l’utilisation sur tout nouveau thread d’arrière-plan. Examen de l’instance de connexion d’entité En recréant la connexion d’entité à partir de zéro, les valeurs guidées sont différentes pour chaque thread et aucun conflit ne semble se produire. Notez que l’assembly doit uniquement être le même assemblage que le modèle réside.

 public static EntityConnection GetEntityConnection( // Build the connection ssortingng. var sqlBuilder = new SqlConnectionSsortingngBuilder(); sqlBuilder.DataSource = serverName; sqlBuilder.InitialCatalog = databaseName; sqlBuilder.MultipleActiveResultSets = true; ... var providerSsortingng = sqlBuilder.ToSsortingng(); var sqlConnection = new SqlConnection(providerSsortingng); // Build the emtity connection. Assembly metadataAssembly = Assembly.GetExecutingAssembly(); Assembly[] metadataAssemblies = { metadataAssembly }; var metadataBase = @"res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl"; var dbModelMetadata = Ssortingng.Format(metadataBase, objectContextTypeModelName); // eg: "res://*/Models.MyDatabaseModel.csdl|res://*/Models.MyDatabaseModel.ssdl|res://*/Models.MyDatabaseModel.msl" var modelMetadataPaths = modelMetadata.Split('|'); var metadataWorkspace = new MetadataWorkspace(modelMetadataPaths, metadataAssemblies); var entityDbConnection = new EntityConnection(metadataWorkspace, sqlConnection); return entityDbConnection;