Primero, el código de Entity Framework: configuración de la asociación de clave externa One-To-One utilizando anotaciones

He seguido dos Entidades que trato de relacionar (una a una) usando asociaciones de claves foráneas.

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; } } 

Esto arroja ModelValidationException. Alguna idea de por qué una relación bidireccional uno a uno aparentemente simple no se puede configurar.

Editar:

Aquí está la excepción:

Se detectó System.Data.Entity.ModelConfiguration.ModelValidationException Message = Uno o más errores de validación se detectaron durante la generación del modelo:

System.Data.Edm.EdmAssociationEnd:: La multiplicidad no es válida en la función ‘StandardRelay_StandardRack_Source’ en la relación ‘StandardRelay_StandardRack’. Debido a que las propiedades del rol dependiente no son las propiedades clave, el límite superior de la multiplicidad del rol dependiente debe ser * .

Source = EntityFramework StackTrace: en System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl (modelo de EdmModel, escritor de XmlWriter) en System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl (modelo de EdmModel) en System.Data.Entity .DbModelBuilder.Build (proveedor de DbProviderManifestManifest, DbProviderInfo providerInfo) en System.Data.Entity.DbModelBuilder.Build (DbConnection providerConnection) en System.Data.Entity.Internal.LazyInternalContext.CreateModel (LazyInternalContext internalContext) en 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 () en 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 () en System.Collections.Generic.List 1..ctor(IEnumerable colección 1..ctor(IEnumerable 1) en System.Linq.Enumerable.ToList [TSource] (fuente IEnumerable`1) en TestApplication .MainWindow.Window_Loaded (Object Sender, RoutedEventArgs e) en D: \ RailwayProjects \ RelayAnalysis \ TestApplication \ MainWindow.xaml.cs: línea 33 InnerException:

Creo que ForeignKey debería ser Id, no StandardRack_id. Además, debe usar virtual, para poder usar la carga diferida.

Esto funciona para mí

 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(); } } } 

Las asociaciones de claves foráneas uno a uno no son compatibles con Entitiy Framework. Debe eliminar la clave externa y usar claves primarias compartidas (la clave principal del dependiente es su clave externa al principal al mismo tiempo):

 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; } } 

Mapeo en API Fluent:

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

(Estoy suponiendo aquí que un StandardRack tiene un relé opcional).

A continuación, le mostramos cómo puede especificar una relación de uno a uno con FK usando una API apta.

Tenga en cuenta que FK no está definido explícitamente en Enitity, pero se define utilizando una API apta.

 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"))); 

La api fluida agregará la columna StandardRack_Id en StandardRelay .

Tenga en cuenta que el nombre del método WithOptionalPrincipal () es bastante irónico. La documentación de msdn de WithOptionalDependent lo dejará en claro.

Es posible que desee adaptar la anotación de ID en StandardRelay. También vea esta pregunta relacionada:

¿Qué significa el final principal de una asociación en una relación 1: 1 en el marco de la Entidad?

 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;} }