2013-03-06 5 views
1

entité relation-cadre je les modèles foloowing:question

public class Employee 
    { 
     public int ID { get; set; } 
     public string name { get; set; } 
     public int LocationID { set; get; } 

     public virtual Location Location { set; get; } 

    } 
    public class Location { 

     public int ID { set; get; } 
     public string NAME { set; get; } 
     public virtual ICollection<Employee> LocationEmployees { get; set; } 

    } 

Fondamentalement, un employé appartient à un emplacement et un emplacement a beaucoup d'employés. Je veux ajouter une colonne au modèle d'emplacement appelé contact de localisation qui sera un identifiant d'employé. J'ai essayé de l'ajouter à travers les premières migrations de code mais cela ne donne pas les résultats attendus.

colonnes Ajouté

public class Employee 
    { 
     public int ID { get; set; } 
     public string name { get; set; } 
     public int LocationID { set; get; } 

     public virtual Location Location { set; get; } 

    } 
    public class Location { 

     public int ID { set; get; } 
     public string NAME { set; get; } 

     public int EmployeeID { get; set; } 

     public virtual Employee Employee { get; set; } 
     public virtual ICollection<Employee> LocationEmployees { get; set; } 

    } 

fichier de migration généré:

public override void Up() 
     { 
      DropForeignKey("dbo.Employees", "LocationID", "dbo.Locations"); 
      DropIndex("dbo.Employees", new[] { "LocationID" }); 
      RenameColumn(table: "dbo.Employees", name: "LocationID", newName: "Location_ID"); 
      AddColumn("dbo.Locations", "EmployeeID", c => c.Int(nullable: true)); 
      AddForeignKey("dbo.Employees", "Location_ID", "dbo.Locations", "ID"); 
      AddForeignKey("dbo.Employees", "LocationID", "dbo.Locations", "ID", cascadeDelete: false); 
      AddForeignKey("dbo.Locations", "EmployeeID", "dbo.Employees", "ID", cascadeDelete: false); 
      CreateIndex("dbo.Employees", "Location_ID"); 
      CreateIndex("dbo.Employees", "LocationID"); 
      CreateIndex("dbo.Locations", "EmployeeID"); 
     } 

     public override void Down() 
     { 
      DropIndex("dbo.Locations", new[] { "EmployeeID" }); 
      DropIndex("dbo.Employees", new[] { "LocationID" }); 
      DropIndex("dbo.Employees", new[] { "Location_ID" }); 
      DropForeignKey("dbo.Locations", "EmployeeID", "dbo.Employees"); 
      DropForeignKey("dbo.Employees", "LocationID", "dbo.Locations"); 
      DropForeignKey("dbo.Employees", "Location_ID", "dbo.Locations"); 
      DropColumn("dbo.Locations", "EmployeeID"); 
      RenameColumn(table: "dbo.Employees", name: "Location_ID", newName: "LocationID"); 
      CreateIndex("dbo.Employees", "LocationID"); 
      AddForeignKey("dbo.Employees", "LocationID", "dbo.Locations", "ID", cascadeDelete: false); 
     } 

Je reçois cette erreur:

System.Data.SqlClient.SqlException (0x80131904): Foreign key 'FK_dbo.Employees_dbo.Locations_LocationID' references invalid column 'LocationID' in referencing table 'Employees'. 
Could not create constraint. See previous errors. 
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) 
    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) 
    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading, Boolean auto) 
    at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 
    at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore() 
    at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run() 
Foreign key 'FK_dbo.Employees_dbo.Locations_LocationID' references invalid column 'LocationID' in referencing table 'Employees'. 
Could not create constraint. See previous errors. 

Qu'est-ce que je manque?

Répondre

2

Je ne sais pas exactement pourquoi la migration lance cette exception mais il est évident qu'elle ne crée pas les relations que vous voulez avoir. Vous pouvez le voir dans la méthode Up lorsque trois clés étrangères sont ajoutées à la place de deux. EF crée trois relations ici, l'une d'elles a le nom FK par défaut Location_ID.

La raison est que EF ne sait pas si Employee.Location a Location.Employee ou Location.LocationEmployees comme propriété de navigation inverse.

Vous devez définir explicitement soit avec annotations de données ...

public class Employee 
{ 
    //... 

    [InverseProperty("LocationEmployees")] 
    public virtual Location Location { set; get; } 
} 

... ou avec l'API Courant:

modelBuilder.Entity<Location>() 
    .HasMany(l => l.LocationEmployees) 
    .WithRequired(e => e.Location) 
    .HasForeignKey(e => e.LocationID); 

modelBuilder.Entity<Location>() 
    .HasOptional(l => l.Employee) 
    .WithMany() 
    .HasForeignKey(l => l.EmployeeID); 

Notez que je l'ai utilisé HasOptional au lieu de HasRequired dans la deuxième relation qui signifie que vous devez également rendre le FK dans votre Location modèle nullable:

public int? EmployeeID { get; set; } 

Les deux relations ne peuvent pas être requises car il n'existe aucune commande valide Employee et Location des entités pourraient être insérées dans la base de données car elles dépendraient mutuellement l'une de l'autre.

Vous pouvez également faire l'autre relation avec int? LocationID dans Employee optionnelle si cela correspond mieux aux besoins de votre entreprise.

+0

Merci beaucoup. J'espère un jour atteindre votre compréhension d'EF. – mpora