Entity Framework Code First: Impostazione dell’associazione di chiavi esterne One-To-One tramite Annotazioni

Ho seguito due Entità che sto cercando di mettere in relazione (uno a uno) usando le associazioni di chiavi estranee.

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.

Modificare:

Ecco l’eccezione:

System.Data.Entity.ModelConfiguration.ModelValidationException è stato rilevato Messaggio = Uno o più errori di convalida 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: su System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl (modello EdmModel, writer XmlWriter) su System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl (modello EdmModel) su System.Data.Entity .DbModelBuilder.Build (DbProviderManifest providerManifest, DbProviderInfo providerInfo) su System.Data.Entity.DbModelBuilder.Build (DbConnection providerConnection) su System.Data.Entity.Internal.LazyInternalContext.CreateModel (LazyInternalContext internalContext) su 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.Initialize () su System.Data.Entity.Internal.Linq.InternalSet 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery 1.System.Collections.Generic.IEnumerable.GetEnumerator () a System.Collections.Generic.List 1..ctor(IEnumerable raccolta 1..ctor(IEnumerable 1) in System.Linq.Enumerable.ToList [TSource] (IEnumerable`1 source) in TestApplication .MainWindow.Window_Loaded (mittente dell’object, RoutedEventArgs e) in D: \ RailwayProjects \ RelayAnalysis \ TestApplication \ MainWindow.xaml.cs: riga 33 InnerException:

Penso che 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(null); } public DbSet StandardRacks { get; set; } public DbSet 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(); } } } 

Entitiy Framework non supporta le associazioni di chiavi esterne one-to-one. È necessario rimuovere la chiave esterna e utilizzare le chiavi primarie condivise (la chiave primaria del dipendente è la chiave esterna all’ quadro principale 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; } } 

Mappatura in API Fluent:

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

(Sto affermando qui che uno StandardRack ha un Relay opzionale.)

Ecco come è ansible specificare la relazione uno a uno con FK usando l’API fluente.

Nota che FK non è esplicitamente definito in Enitity, ma è definito usando 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() .HasOptional(x => x.StandardRelay) .WithOptionalPrincipal(y => y.StandardRack) .Map(configurationAction: new Action(x => x.MapKey("StandardRack_Id"))); 

api fluente aggiungerà colonna StandardRack_Id in StandardRelay .

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

Potresti voler adattare l’annotazione dell’ID in StandardRelay. Vedi anche questa domanda correlata:

Cosa significa il termine principale di un’associazione nella relazione 1: 1 nel framework Entity

 public class Foo { public string FooId{get;set;} public Boo Boo{get;set;} } public class Boo { [Key, ForeignKey("Foo")] public string BooId{get;set;} public Foo Foo{get;set;} }