21

Estoy tratando de crear una aplicación rápida de ASP.NET MVC 3 utilizando la versión RC de EF 4.1. Tengo dos modelos:EF 4.1 - Relaciones de modelo

public class Race 
{ 
    public int RaceId { get; set; } 
    public string RaceName { get; set; } 
    public string RaceDescription { get; set; } 
    public DateTime? RaceDate { get; set; } 
    public decimal? Budget { get; set; } 
    public Guid? UserId { get; set; } 
    public int? AddressId { get; set; } 

    public virtual Address Address { get; set; } 
} 

y

public class Address 
{ 
    public int AddressId { get; set; } 
    public string Street { get; set; } 
    public string StreetCont { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 

    public virtual Race Race { get; set; } 
} 

me sale el siguiente error al intentar insertar una nueva Raza:

No se puede determinar el fin principal de una asociación entre los tipos 'rcommander.Models.Race' y 'rcommander.Models.Address'. El extremo principal de de esta asociación debe estar explícitamente configurado utilizando la relación con la API o las anotaciones de datos .

¿No debería reconocer RaceId como la clave principal de la tabla Races y AddressId como el FK de la tabla Direcciones automáticamente? ¿Me estoy perdiendo de algo?

Gracias!

Respuesta

21

El problema aquí parece ser que EntityFramework no puede reconocer dónde está la clave externa, ya que tiene referencias cruzadas en ambos objetos. No estar seguro de lo que quiere lograr, puedo sugerir algo como esto:

public class Race 
{ 
    public int RaceId { get; set; } 
    public string RaceName { get; set; } 
    public string RaceDescription { get; set; } 
    public DateTime? RaceDate { get; set; } 
    public decimal? Budget { get; set; } 
    public Guid? UserId { get; set; } 

    public int? AddressId { get; set; } 
    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
    public int AddressId { get; set; } 
    public string Street { get; set; } 
    public string StreetCont { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 
} 

referencia Saltarse para la carrera en segunda entidad.

+0

Eso fue todo. Gracias. – Mike

+4

¿no eliminará esto las posibilidades de navegación de la dirección? –

+1

Sí, eliminará la posibilidad de navegación de la dirección y la correlacionará como una relación uno a muchos como describí en mi respuesta. –

4

Reconoce Id como la clave principal por convención. Así que lo que tiene que hacer:

public class Race 
{ 
    [Key] 
    public int RaceId { get; set; } 
    public string RaceName { get; set; } 
    public string RaceDescription { get; set; } 
    public DateTime? RaceDate { get; set; } 
    public decimal? Budget { get; set; } 
    public Guid? UserId { get; set; } 
    public int? AddressId { get; set; } 

    public virtual Address Address { get; set; } 
} 
and 

public class Address 
{ 
    [Key] 
    public int AddressId { get; set; } 
    public string Street { get; set; } 
    public string StreetCont { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 

    [ForeignKey("RaceId")] // Maybe telling it what the ForeignKey is will help? 
    public virtual Race Race { get; set; } 
} 

El atributo [Key] indica que debería ser el PrimaryKey

Si no desea esto, es necesario cambiar el nombre de sus claves primarias simplemente public int Id {get; set; }

+1

mismo error utilizando cualquiera de los métodos. Tengo mi iniciador de base de datos en Application_Start en Global.asax para DropCreateDatabaseIfModelChanges si eso es lo que importa. – Mike

+1

Hmm ... Verifique mi actualización ... ¿Tal vez ForeignKeyAttribute es lo que necesita? –

+1

¿No es InverseProperty ("RaceId") lo que se necesita aquí, no ForeignKey? – Joe

18

¡El problema aquí es la relación 1: 1 entre la dirección y la raza! Es posible que desee hacer un mapa de 1: N por lo que resulta necesario modificar la dirección a:

public class Address 
{ 
    public int AddressId { get; set; } 
    public string Street { get; set; } 
    public string StreetCont { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 

    public virtual ICollection<Race> Races { ... } 
} 

Si desea utilizar 1: 1, entonces no se puede utilizar en la carrera, pero AddressID AddressID en dirección debe ser clave externa de Raza porque el marco de la entidad puede lograr 1: 1 solo ser "compartir" la clave principal.

+3

¿Puede actualizar su respuesta para mostrar cómo usar 1: 1 con la clave primaria compartida? Me gustaría tener una forma bidireccional de acceder así: Race.Address y Address.Race. Mantenga la raza y la dirección si es posible en su ejemplo. Gracias. –

+1

@Leniel: Marque esta respuesta: http://stackoverflow.com/questions/5388077/primary-foreign-key-in-entity-framework/5388658#5388658 Creo que es lo que está buscando. –

5

Hay un buen post: Asociaciones en Código EF Primera CTP5: Parte 2 - compartidos Asociaciones de clave principal

http://weblogs.asp.net/manavi/archive/2010/12/19/entity-association-mapping-with-code-first-one-to-one-shared-primary-key-associations.aspx

+0

"Una forma de hacer que nuestras asociaciones sean uno a uno es haciéndolas bidireccionales. Es decir, agregando una nueva propiedad de navegación a la clase Dirección de tipo Usuario y otra de tipo Envío." - esto no parece funcionar . Obtengo el mensaje "No se puede determinar el extremo principal de una asociación entre los tipos ... El extremo principal de esta asociación debe configurarse explícitamente utilizando la relación API o anotaciones de datos con fluidez". – Karan

8

Para uno-a-uno, es necesario agregar "[requerido]" atributo en la segunda clase. Ver más abajo:

public class Race 
{ 
    public int RaceId { get; set; } 
    public string RaceName { get; set; } 
    public string RaceDescription { get; set; } 
    public DateTime? RaceDate { get; set; } 
    public decimal? Budget { get; set; } 
    public Guid? UserId { get; set; } 

    public int? AddressId { get; set; } 
    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
public int AddressId { get; set; } 
public string Street { get; set; } 
public string StreetCont { get; set; } 
public string City { get; set; } 
public string State { get; set; } 
public string ZipCode { get; set; } 

[required] 
public Race Race { get; set; } 

} 
0

creo que se solucionaría también como esto ... Supuse que una dirección no está obligado a estar asociado con una carrera, pero una carrera siempre debe estar asociado con una dirección. tuve el mismo problema con los pacientes y los incidentes y lo resolví con InverseProperty que en realidad es lo mismo con la clave externa, pero la otra dirección

public class Race 
{ 
    public int RaceId { get; set; } 
    public string RaceName { get; set; } 
    public string RaceDescription { get; set; } 
    public DateTime? RaceDate { get; set; } 
    public decimal? Budget { get; set; } 
    public Guid? UserId { get; set; } 

    public int AddressId { get; set; } 

    [ForeignKey("AddressId")] 
    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
public int AddressId { get; set; } 
public string Street { get; set; } 
public string StreetCont { get; set; } 
public string City { get; set; } 
public string State { get; set; } 
public string ZipCode { get; set; } 

public int? RaceId { get; set; } 
[InverseProperty("RaceId")] 
public Race Race { get; set; } 

} 
Cuestiones relacionadas