c # trabajando con Entity Framework en un servidor multiproceso

¿Cuál es la mejor práctica para trabajar con el marco de la entidad en un servidor multiproceso? Estoy utilizando el marco de trabajo de la entidad ObjectContext para administrar todas las acciones de mi base de datos, ahora sé que este contexto no es seguro para subprocesos, así que por ahora cuando necesito usarlo para realizar algunas acciones de DB, lo rodeo con la statement de lock para estar seguro. ¿Es así como debería hacerlo?

Algunos consejos rápidos para Entity Framework en un entorno de subprocesos múltiples:

  • No use un contexto único con locks (ningún patrón singleton)
  • Proporcionar servicios apátridas (necesita instanciar y disponer un contexto por solicitud )
  • Acortar el tiempo de vida del contexto tanto como sea posible
  • Implemente un sistema de control de concurrencia . La concurrencia optimista se puede implementar fácilmente con Entity Framework ( cómo hacerlo ). Esto asegurará que no sobrescriba los cambios en el DB cuando usa una entidad que no está actualizada

Estoy un poco confundido, pensé que usar un contexto es bueno porque creo que atrapa un poco, así que cuando trato con la misma entidad en solicitudes consecutivas, es mucho más rápido usar el mismo contexto y luego crear un nuevo contexto cada vez. Entonces, ¿por qué es bueno usarlo así si es más lento y aún no es seguro?

Puede usar solo un contexto, pero se desaconseja enfáticamente a menos que realmente sepa lo que está haciendo .

Veo dos problemas principales que a menudo suceden con este enfoque:

  1. usará mucha memoria ya que su contexto nunca será eliminado y todas las entidades manipuladas se almacenarán en la memoria (cada entidad que aparece en el resultado de una consulta se almacena en caché).

  2. se enfrentarán muchos problemas de simultaneidad si modifica los datos de otro progtwig / contexto. Por ejemplo, si modifica algo directamente en su base de datos y la entidad asociada ya estaba en caché en su objeto de contexto único, entonces su contexto nunca sabrá sobre la modificación que se realizó directamente en la base de datos. Trabajará con una entidad en caché que no está actualizada, y créame, provocará problemas difíciles de encontrar y corregir.

Además, no se preocupe por el rendimiento del uso de contextos múltiples : la sobrecarga de crear / eliminar un nuevo contexto por solicitud es casi insignificante en el 90% de los casos de uso. Recuerde que crear un nuevo contexto no necesariamente crea una nueva conexión a la base de datos (ya que la base de datos generalmente usa un grupo de conexiones).

¿Es así como debería hacerlo?

No. Como mínimo, use un contexto por hilo, pero le recomiendo encarecidamente que piense en un contexto como unidad de trabajo y, por lo tanto, use un contexto por unidad de trabajo por hilo.

Depende de usted definir “unidad de trabajo” para su aplicación. Pero no use el lock para usar un contexto en varios hilos. No escala.

Está tratando ObjectContext como si fuera una entidad extremadamente costosa, por lo que está instanciando una vez y luego tratándola como una “fachada”. No hay necesidad de hacer esto. Si, por ninguna otra razón, las conexiones se agrupan debajo del capó y cuestan muy poco (¿microsegundos? – ¿probablemente menos?) Para configurar completamente la “cadena de objetos” para usar la abstracción ObjectContext.

ObjectContext, al igual que el uso directo de SqlConnection, etc., está diseñado para ser utilizado con una metodología de “crear instancias lo más tarde posible y descargar lo antes posible”.

EF le brinda cierta seguridad ya que tiene la capacidad de probar si tiene los últimos objetos antes de comprometerse (Concurrencia optimista). Esto no significa “hilo seguro”, per se, pero logra lo mismo si respetas las reglas.

Normalmente, ObjectContext no se debe usar globalmente en toda la aplicación. Debe crear nuevos ObjectContexts con frecuencia y deshacerse de los viejos. Ciertamente tampoco son enhebrables. Si continúa utilizando el mismo ObjectContext (dependiendo de la duración de su aplicación) es fácil obtener una excepción de falta de memoria si modifica cantidades masivas de datos ya que el contexto del objeto contiene referencias a las entidades que cambia.

Creo un nuevo contexto para cada operación atómica y dispongo el contexto. Por lo que sé de libros y artículos, prefiero mantener el tiempo de vida del contexto lo más breve posible. (pero depende de su enfoque y su tipo de aplicación, winform o web)

Por favor encuentre más información en el gran artículo. http://www.west-wind.com/weblog/posts/2008/Feb/05/Linq-to-SQL-DataContext-Lifetime-Management

Buenos libros: 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 = resultado y resnum = 2 & ved = 0CCgQ6AEwAQ # v = onepage & q & f = false

Discusión existente en Datacontext Lifetime en WinForm Binding Scenario

Utilizo el marco de entidad en un entorno de subprocesos múltiples, donde cualquier subproceso, interfaz de usuario y fondo (tanto STA como MTA) pueden actualizar simultáneamente la misma base de datos. Resolví este problema al volver a crear la conexión de entidad desde cero al comienzo del uso en cualquier nueva cadena de fondo. Examinando la instancia de conexión de la entidad ConnectionString muestra una guía de lectura que, supongo, se usa para vincular instancias de conexión comunes. Al recrear la conexión de entidad desde cero, los valores de guid son diferentes para cada subproceso y no parece que se produzca ningún conflicto. Tenga en cuenta que el ensamblaje solo debe ser del mismo ensamblaje que el modelo.

 public static EntityConnection GetEntityConnection( // Build the connection string. var sqlBuilder = new SqlConnectionStringBuilder(); sqlBuilder.DataSource = serverName; sqlBuilder.InitialCatalog = databaseName; sqlBuilder.MultipleActiveResultSets = true; ... var providerString = sqlBuilder.ToString(); var sqlConnection = new SqlConnection(providerString); // Build the emtity connection. Assembly metadataAssembly = Assembly.GetExecutingAssembly(); Assembly[] metadataAssemblies = { metadataAssembly }; var metadataBase = @"res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl"; var dbModelMetadata = String.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;