2013-02-11 15 views
7

Mam problem z nawigacją zwrotną w jednym z moich podmiotów.Jeden do jednego związku z Entity Framework Fluent API

Mam następujące dwa obiekty:

public class Candidate 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long CandidateId { get; set; } 
    .... 

    // Reverse navigation 
    public virtual CandidateData Data { get; set; } 
    ... 

    // Foreign keys 
    .... 
} 

public class CandidateData 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long CandidateDataId { get; set; } 

    [Required] 
    public long CandidateId { get; set; } 

    // Foreign keys 
    [ForeignKey("CandidateId")] 
    public virtual Candidate Candidate { get; set; } 
} 

Teraz mój klawisz nawigacyjny zagranicznych na obiekcie CandidateData działa dobrze. Mam problem z uruchomieniem nawigacji wstecznej dla obiektu kandydata do pracy (jeśli to nawet możliwe).

To jest moja funkcja OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

    modelBuilder.Entity<Candidate>() 
     .HasOptional(obj => obj.Data) 
     .WithOptionalPrincipal(); 

    base.OnModelCreating(modelBuilder); 
} 

Jest blisko do pracy, z wyjątkiem danych mam dwie kolumny, które linkują do CandidateId. Otrzymuję jeden z obiektu POCO, otrzymuję kolejną kolumnę Candidate_CandidateId Zakładam, że został stworzony przez modelBuilder.

Jestem cicho zagubiony w tej chwili. Czy ktoś może rzucić trochę światła na to, co się dzieje?

+0

Dlaczego definiujesz dodatkowe pole, takie jak [Wymagane] public long CandidateId {get; zestaw; } Usuń i twoje problemy znikną –

+0

Myślę, że twoja relacja powinna być modelBuilder.Entity () .HasOptional (obj => obj.Data) .WithRequired (e => e.Candidate); BTW: staraj się nie mieszać płynnego API i atrybutów. – tschmit007

Odpowiedz

13

Problem Jeden do jednego .... Problem jest EF i KODEK Najpierw, gdy 1: 1, dla osoby zależnej klucz podstawowy, który odnosi się do zleceniodawcy. Chociaż można zdefiniować DB inaczej, a nawet z DB można nawet mieć OPCJONALNE FK na podstawowej. EF najpierw robi to ograniczenie w Kodzie. Fair Enough myślę ...

Spróbuj tego zamiast: Czy dodaliśmy kilka opinie na drodze, które mogą Cię ignorowanych jeśli nie zgadzasz :-)

using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
namespace EF_DEMO 
{ 
class FK121 
{ 
    public static void ENTRYfk121(string[] args) 
    { 
     var ctx = new Context121(); 
     ctx.Database.Create(); 
     System.Console.ReadKey(); 
    } 
} 
public class Candidate 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]// best in Fluent API, In my opinion.. 
    public long CandidateId { get; set; } 
// public long CandidateDataId { get; set; }// DONT TRY THIS... Although DB will support EF cant deal with 1:1 and both as FKs 
    public virtual CandidateData Data { get; set; } // Reverse navigation 

} 
public class CandidateData 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] // best in Fluent API as it is EF/DB related 
    public long CandidateDataId { get; set; } // is also a Foreign with EF and 1:1 when this is dependent 
    // [Required] 
    // public long CandidateId { get; set; } // dont need this... PK is the FK to Principal in 1:1 
    public virtual Candidate Candidate { get; set; } // yes we need this 
} 
public class Context121 : DbContext 
{ 
    static Context121() 
    { 
     Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>()); 
    } 
    public Context121() 
     : base("Name=Demo") { } 
    public DbSet<Candidate> Candidates { get; set; } 
    public DbSet<CandidateData> CandidateDatas { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Candidate>(); 

     modelBuilder.Entity<CandidateData>() 
        .HasRequired(q => q.Candidate) 
        .WithOptional(p=>p.Data) // this would be blank if reverse validation wasnt used, but here it is used 
        .Map(t => t.MapKey("CandidateId")); // Only use MAP when the Foreign Key Attributes NOT annotated as attributes 
    } 
} 

}

+0

Dziękuję, to mniej lub bardziej rozwiązało problem dla mnie. Chociaż nadal chciałbym mieć pole CandidateId dostępne dla mnie do edycji w locie i bez konieczności ładowania obiektu Candidate. (Czy interpretuję to niepoprawnie?) Jeszcze raz dziękuję, William. – William

+0

Jeśli nadal chcesz mieć klucz obcy, możesz zachować CandidateId jako właściwość w CandidateData, a zamiast wywoływać .Map (t => t.MapKey ("CandidateId")) użyj .HasForeignKey (t => t.CandidateId) Czy to nie zadziała? –

+0

@NathanaelSchulte To nie działa, niestety. Dlaczego nie możesz tego zrobić, nie mam pojęcia. Metoda .HasForeignKey() jest dostępna tylko w przypadku użycia wielu. Problem z podejściem phil soady polega na tym, że klucz obcy, CandidateId, nie może wtedy zostać ujawniony jako jawna właściwość modelu, tj. Nie można zdefiniować CandidateId w klasie CandidateData. – Aernor

-2

Myślę, że klucz obcy powinien być utworzony jako: .Mapa (t => t.MapKey ("CandidateDataId")), ponieważ ten klucz obcy zostanie umieszczony w tabeli Kandydata ...

Waht, myślisz?

Powiązane problemy