2012-04-11 11 views
11

Ho seguito due entità che sto cercando di mettere in relazione (uno a uno) usando le associazioni di chiavi esterne.Codice quadro entità Primo: configurazione dell'associazione di chiavi esterne One-To-One mediante Annotazioni

public class StandardRack { 
    public int Id {get;set} 
    public StandardRelay StandardRelay {get;set} 
} 

public class StandardRelay { 
    public int Id {get;set} 

    public int StandardRack_Id {get;set;} 
    [Required][ForeignKey("StandardRack_Id")] 
    public StandardRack StandardRack { get; set; } 
} 

Questo genera ModelValidationException. Qualche idea sul perché una tale relazione bidirezionale apparentemente semplice non possa essere configurata.

Edit:

Qui è l'eccezione:

System.Data.Entity.ModelConfiguration.ModelValidationException è stato catturato Messaggio = Uno o più errori di validazione sono stati rilevati durante la generazione del modello:

System.Data.Edm.EdmAssociationEnd:: Multiplicity non è valido nel ruolo 'StandardRelay_StandardRack_Source' nella relazione 'StandardRelay_StandardRack'. Poiché le proprietà del ruolo dipendente non sono le proprietà chiave, il limite superiore della molteplicità del ruolo dipendente deve essere * .

Source = EntityFramework StackTrace: a System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl (modello EdmModel, XmlWriter scrittore) a System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl (modello EdmModel) a System.Data.Entity.DbModelBuilder.Build (DbProviderManifest providerManifest, DbProviderInfo providerInfo) a System.Data.Entity.DbModelBuilder.Build (DbConnection ProviderConnection) a System.Data.Entity.Internal.LazyInternalContext.CreateModel (LazyInternalContext internalContext in System.Data.Entity.Internal.RetryLazy 2.GetValue(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.Initialize() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet 1. Inizializza() a System.Data.Entity.Internal.Linq.InternalSet 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery 1.System.Collections.Generic.IEnumerable.GetEnumerator() a System.Collections.Generic.List 1..ctor(IEnumerable 1 collezione) a System.Linq.Enumerable.ToList [ TSource] (fonte IEnumerable`1) a TestApplication.MainWindow.Window_Loaded (object sender, RoutedEventArgs e) in D: \ RailwayProjects \ RelayAnalysis \ TestApplication \ MainWindow.xaml.cs: linea 33 InnerException:

+0

Puoi pubblicare il messaggio dettagliato di 'ModelValidationException' incluse le possibili eccezioni interne? – Slauma

+0

Si prega di vedere il mio EDIT per l'eccezione – Jatin

risposta

8

Penso che il foreignKey dovrebbe essere Id, non StandardRack_id. Inoltre, dovresti usare virtual, per poter usare il caricamento lazy.

questo funziona per me

using System.ComponentModel.DataAnnotations; 
using System.Data.Entity; 

namespace Racks 
{ 

    public class StandardRack 
    { 
     public int Id { get; set; } 
     public virtual StandardRelay StandardRelay { get; set; } 
    } 

    public class StandardRelay 
    { 
     public int Id { get; set; } 

     public int StandardRack_Id { get; set; } 

     [ForeignKey("Id")] 
     [Required] 
     public virtual StandardRack StandardRack { get; set; } 
    } 

    public class Context : DbContext 
    { 
     static Context() 
     { 
      Database.SetInitializer<Context>(null); 
     } 

     public DbSet<StandardRack> StandardRacks { get; set; } 
     public DbSet<StandardRelay> StandardRelays { get; set; } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var context = new Context(); 
      context.Database.Delete(); 
      context.Database.Create(); 

      var standardRack = new StandardRack(); 
      standardRack.StandardRelay = new StandardRelay(); 

      context.StandardRacks.Add(standardRack); 
      context.SaveChanges(); 
     } 
    } 
} 
+0

Arialdo, @Slauma, gli approcci suggeriti da entrambi comportano la stessa struttura del database, ovvero la colonna Id di StandardRack funge da destinazione della chiave esterna (Id) di StandardRelay. Andrò con l'approccio di Arialdo e segnerò la sua risposta come corretta, sebbene entrambe le risposte funzionino. – Jatin

+0

+1 Buona idea! Non mi aspettavo che la mappatura one-to-one funzionasse anche con le annotazioni. Mi chiedo se funzioni anche se rimuovi l'attributo '[ForeignKey] del tutto (ma lasci l'attributo' [Required] 'in posizione). L'hai provato? – Slauma

+1

@Slauma, Anche se rimuovo il Foreignkey, funziona e crea la stessa struttura del Database. Così Foreignkey può essere lasciato fuori del tutto.Grazie mille ad entrambi per avermi aiutato. – Jatin

23

One Le associazioni di chiavi straniere non sono supportate da Entitiy Framework. È necessario rimuovere la chiave esterna e utilizzare chiavi primarie condivise (chiave primaria della dipendenza è la sua chiave esterna al capitale allo stesso tempo):

public class StandardRack { 
    public int Id {get;set} 
    public StandardRelay StandardRelay {get;set} 
} 

public class StandardRelay { 
    public int Id {get;set} 
    public StandardRack StandardRack { get; set; } 
} 

Mapping API Fluent:

modelBuilder.Entity<StandardRack>() 
    .HasOptional(rack => rack.StandardRelay) 
    .WithRequired(relay => relay.StandardRack); 

(Sto asserendo qui che un StandardRack ha un relè opzionale.)

+0

Personalmente preferisco questo approccio a quello che ho postato sopra: Mi piacciono le entità indipendenti dal database, quindi cerco sempre di evitare annotazioni. +1 –

+2

Inoltre, nota: per utilizzare il caricamento lazy, è necessario aggiungere 'virtuale' a proprietà non primitive. –

+0

Non supportato da Entity Framework o da Code First specificamente? Abbastanza sicuro che questo funziona in edmx. –

3

Ecco come è possibile specificare uno-a-uno con l'FK utilizzando api fluente.

Nota che FK non è definito in modo esplicito in Enitity, ma è definito utilizzando fluenti API.

public class StandardRack { 
    public int Id {get;set} 
    public StandardRelay StandardRelay {get;set} 
} 

public class StandardRelay { 
    public int Id {get;set} 
    public StandardRack StandardRack { get; set; } 
} 


modelBuilder.Entity<StandardRack>() 
      .HasOptional(x => x.StandardRelay) 
      .WithOptionalPrincipal(y => y.StandardRack) 
      .Map(configurationAction: new Action<ForeignKeyAssociationMappingConfiguration>(x => x.MapKey("StandardRack_Id"))); 

API fluente aggiungerà colonna StandardRack_Id in StandardRelay.

Si noti che il nome del metodo WithOptionalPrincipal() è abbastanza ironico. la documentazione di msdn di WithOptionalDependent deve essere chiara.

+0

Nessuno menziona mai '.Map' e' .MapKey', grazie per aver postato questo! – Langdon

+0

Grazie, il mio risparmio di tempo! :-) – VikciaR

Problemi correlati