21

He desarrollado una pequeña aplicación de demostración WPF que utiliza EF-Code First para guardar sus datos en una base de datos SQL CE 4.0. Funciona bien, a menos que elimine una propiedad de un objeto modelo. Por ejemplo, si quito "HosteBy" de esta clase .....Código de Entity Framework-Primero: ¿Cómo actualizar manualmente la base de datos?

public class Dinner 
{ 
    public int DinnerID { get; set; } 
    public string Title { get; set; } 
    public DateTime EventDate { get; set; } 
    public string Address { get; set; } 
    public string HostedBy { get; set; } 

    public virtual ICollection<RSVP> RSVPs { get; set; } 
} 

... que emite esta excepción:

El modelo respaldo del contexto '' NerdDinners ha cambiado desde la la base de datos fue creada. Elimine/actualice manualmente la base de datos o llame a Database.SetInitializer con una instancia de IDatabaseInitializer. Por ejemplo, la estrategia DropCreateDatabaseIfModelChanges eliminará automáticamente y volverá a crear la base de datos y, opcionalmente, la inicializará con nuevos datos.

El error persiste incluso después de eliminar manualmente el campo "HosteBy" de la base de datos. ¿Que me estoy perdiendo aqui? ¿Debo eliminar/truncar el archivo db o hay otra solución?

Respuesta

25

En el primer escenario en el que ha cambiado el primer código del modelo, antes de ingresar y modificar la base de datos de forma manual, la respuesta es abrir la consola y el tipo (Nuget) Gestor de paquetes:

update-database -verbose 

Excepto - porque en este Si está eliminando una columna, esto informará que está a punto de eliminar algo, y no eliminará nada sin que explícitamente indique que está bien.Entonces escribe:

update-database -f -verbose 

Ahora esto eliminará la columna que tenía en su Modelo. -verbose dice que le muestre el SQL que ejecuta. Si tienes miedo de que acaba de dejar borrar las cosas y en vez inspeccionar el SQL antes de que funcione, utilice:

actualización de la base de datos-f -script

Ese lugar será volcar el SQL a una secuencia de comandos se puede ver más, y ejecutar manualmente usted mismo.

En el caso en que siguió y borró la columna en la base de datos manualmente, ahora tiene un escenario más complejo en sus manos; la tabla EdmMetadata descrita en la otra respuesta aquí contiene un hash de toda la base de datos que ahora no coincide con la base de datos en sí. Puede ejecutar SQL manual para devolver el DB a la forma en que Entity Framework espera (tal como era antes de que lo modificara manualmente, lo que lo vuelve a alinear con el hash) inspeccionando lo que tenía antes y cómo se ve actualmente su BD.

Si eso no es posible, ahora se encuentra en la parte más fea de Entity Framework Code First. Debe eliminar la tabla hash e invertir la ingeniería de la base de datos en archivos de código.

El nombre de la tabla hash depende de la versión de EF. En EF4 anterior, como usted preguntaba, se llama EdmMetadata. En EF5 más nuevo, se llama __MigrationHistory (en System Tables en su base de datos si está buscando en SQL Server Management Studio). Tendrás que borrarlo.

La buena noticia sobre el segundo paso, la ingeniería inversa de la base de datos en el código, es que Microsoft ha lanzado una herramienta en beta que hará esto por usted.

Walk-through of reverse-engineering a db, and EF Power Tools

Puede omitir muchos de los primeros pasos que hay ya que son sólo la creación de una base de datos y añadiendo un poco de sentido a la misma para que puedan demostrar lo que tiene que hacer: aplicar ingeniería inversa a una base de datos.

Actualización:

También puede ser factible utilizar una migración manual para evitar este escenario. Hacer una copia de seguridad de la base de datos, a continuación, ejecute:

add-migration WhateverYouWantToCallThis 

Las modificaciones a las migraciones db EF que se deben ejecutar aparecerán en los comandos de C# generadas. Ahora le toca a usted jugar con ellos para resolver los problemas con lo que está intentando hacer (por ejemplo, intentar eliminar columnas que ya han sido eliminadas), y poner en su lugar las cosas que necesitará en el futuro (por ejemplo, volver a agregar una tabla que todavía tiene en su modelo pero que borró manualmente en su db).

Una vez que haya agregado esto y ejecute update-database -f, EF Code First solo aceptará con la fe que ha actualizado la base de datos de la manera que necesita y actualizará su hash en función del resultado final. Si realizó los cambios correctos, ahora puede continuar con Migraciones de forma normal. Si esto sigue causando errores, generalmente puede copiar los comandos de la migración manual en algún lugar y eliminarlos, restaurar el archivo db de su copia de seguridad, agregar una migración manual nuevamente e intentar nuevamente. En el peor de los casos, recurre al paso de ingeniería inversa anterior.

2

Si su base de datos contiene alguna tabla extraña con el nombre EdmMetadata, su contexto utiliza un nivel muy básico de control de versiones de la base de datos. Cuando creó la base de datos, almacenó un hash de su modelo en esta tabla y cada vez que construye un modelo para su aplicación (la primera vez que usa el contexto después de reiniciar su aplicación) nuevamente calcula el hash y lo compara con el hash almacenado en esa mesa. Significa que cualquier cambio en su modelo dará como resultado un hash diferente y EF reaccionará con la excepción que usted ve. El cambio manual en la base de datos no lo ayudará porque la tabla contiene aún el anterior.

Las soluciones son:

  • La eliminación de este control de versiones. Requiere eliminar IncludeMetadataConvention como se describe here.
  • Actualizando el hash. Requeriría la ingeniería inversa del algoritmo para el cálculo de hash (por ejemplo, Red Gate .NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy o Telerik JustDecompile) y el cálculo de hash nuevo del modelo compilado (o utilizando el reflejo para leer la propiedad interna desde DbCompiledModel.ModelHash con ya calculado hash) que almacenará en la tabla EdmMetadata.
  • Eliminación manual de la base de datos y dejar EF crear uno nuevo - se perderán todos los datos
  • inicializador Ajuste a DropCreateDatabaseIfModelChanges - se eliminará automáticamente la base de datos y crear uno nuevo si cambia el modelo - se perderán todos los datos
3
+1

O paso 7 en este tutorial ;-) http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql -ce.aspx La solución es bastante simple: después de haber actualizado la base de datos (eliminó/agregó los campos necesarios manualmente), debe truncar la tabla generada automáticamente "EdmMetadata" ya que almacena un ModelHash en ella. Esto es. – Mike

0

Comprobar la sección de este artículo en Código primeras migraciones con una base de datos existente
http://msdn.microsoft.com/en-us/data/dn579398

veces su proyecto y su base de datos puede obtener fuera de sincronización. Por lo tanto, es posible que tenga que volver a sincronizar su esquema a partir de su base de datos existente.



1) Para crear una migración con sede fuera del esquema existente:
Añadir a la migración InitialCreate

2) Ejecutar Actualización de Base de datos después de eso para agregar la entrada en la tabla _MigrationsHistory para indicar que la migración se completa hasta el esquema existente.

0

Tres cosas simples que usted debe recordar cuando se trabaja en primer código

  1. Enable-Migraciones
  2. Añadir a la migración
  3. Actualización de Base de datos de

todo es auto explicativo.

Debe ejecutar estos comandos en la consola de Package Manager manualmente. Llego tarde pero espero que ayude

Cuestiones relacionadas