23

Ho due classi POCOImplementazione di zero o uno a zero o una relazione nel Codice EF prima da API Fluent

public class Order 
{ 
    int id; 
    string code; 
    int? quotationId; //it is foreign key 
    public int Id{get;set;} 
    public string Code{get;set;} 
    public int? QuotationId{get;set;} 
    Quotation quotation; 
    public virtual Quotation Quotation { get; set; } 
    .... 
} 

public class Quotation 
{ 
    int Id; 
    string Code; 
    public int Id{get;set;} 
    public string Code{get;set;} 
    Order order; 
    public virtual Order Order { get; set; } 
    .... 
} 

ciascun Ordine può fatto da uno o zero citazione, e ogni citazione può causare un ordine , quindi ho una relazione "uno o zero" con "uno o zero", come posso implementarla, in codice EF prima tramite API fluente?

+0

'Quotazione pubblica Quotazione virtuale {get; impostato; } ', no? Perché non stai usando le proprietà? Perché tutti i tuoi campi sono privati? –

+0

scusate, ho modificato il mio codice per le proprietà. le mie lezioni non sono virtuali – Masoud

+0

non è una classe virtuale, è una proprietà di navigazione virale, nella classe Ordine. –

risposta

30

Cambiando pocos a:

public class Order 
{ 
    public int OrderId { get; set; } 
    public virtual Quotation Quotation { get; set; } 
} 
public class Quotation 
{ 
    public int QuotationId { get; set; } 
    public virtual Order Order { get; set; } 
} 

e l'utilizzo di questi file di mapping:

public class OrderMap : EntityTypeConfiguration<Order> 
{ 
    public OrderMap() 
    { 
     this.HasOptional(x => x.Quotation) 
      .WithOptionalPrincipal() 
      .Map(x => x.MapKey("OrderId")); 
    } 
} 

public class QuotationMap : EntityTypeConfiguration<Quotation> 
{ 
    public QuotationMap() 
    { 
     this.HasOptional(x => x.Order) 
      .WithOptionalPrincipal() 
      .Map(x => x.MapKey("QuotationId")); 
    } 
} 

avremo questo DB (che significa 0..1-0 ..1):

enter image description here

con grazie particolare a (Mr. Vahid Nasiri)

procedura
+1

Entrambe le configurazioni hanno 'WithOptionalPrincipal'? – VansFannel

+0

vedere anche questa correzione in 6.1: https://entityframework.codeplex.com/workitem/546 – juFo

+5

Avvertenza: è necessario impostare entrambe le chiavi esterne. Se si imposta solo 'Order.Quotation', solo' Qotations.OrderId' è impostato nel database, non 'Order.QuotationId'. –

4

Adattato da questo answer, provare questo.

In primo luogo, risolvere il tuo classi:

public class Order 
{ 
    public int Id {get; set;} 
    public virtual Quotation Quotation { get; set; } 
    // other properties 
} 

public class Quotation 
{ 
    public int Id {get; set;} 
    public virtual Order Order { get; set; } 
    // other properties 
} 

quindi utilizzare l'API fluente così:

modelBuilder.Entity<Quotation>() 
.HasOptional(quote => quote.Order) 
.WithRequired(order=> order.Quotation); 

In sostanza, per 1: 1 o [0/1]: [0/1] relazioni, EF ha bisogno delle chiavi primarie per essere condivise.

+0

grazie, ma da questa mappatura avremo un-o-one zero a uno relazione. ho trovato la risposta corretta e posta. – Masoud

4

Vedi http://msdn.microsoft.com/en-us/data/jj591620 EF relazioni

un libro eccellente http://my.safaribooksonline.com/book/-/9781449317867

Ecco un post dal sviluppatore da dicembre 2010. Ma ancora rilevante http://social.msdn.microsoft.com/Forums/uk/adonetefx/thread/aed3b3f5-c150-4131-a686-1bf547a68804 L'articolo di cui sopra è un bel riassunto o le combinazioni possibili qui.

Una soluzione in cui la tabella dipendente ha una chiave dalla tabella primaria è possibile.

Se si desiderano chiavi indipendenti in cui entrambi sono principali in uno scenario PK/FK, non penso che si possa farlo in codice prima con Fluent API. Se condividono una chiave, sei OK. 1: 1 opzionale presuppone che il dipendente utilizzi la chiave da Principale.

Ma poiché è necessario salvare uno dei tavoli prima dell'altro. È possibile selezionare una delle chiavi esterne con il codice. O aggiungi il secondo Foreign to Database dopo che Code lo ha creato per primo.

Ti avvicinerai. Ma EF si lamenterà delle chiavi esterne in conflitto se vuoi che siano entrambe chiavi esterne. Essenzialmente A dipende da B dipende A EF non piace, anche se le colonne sono annullabili e tecnicamente possibili sul DB.

Qui utilizzare questo programma di prova per provarlo. Basta commentare le novità di Fluent API per provare alcune opzioni. Non ho potuto ottenere EF5.0 per lavorare con INDKENDENT PK/FK 0: 1 a 0: 1 Ma ovviamente ci sono dei compromessi ragionevoli come discusso.

using System.Data.Entity; 
using System.Linq; 
namespace EF_DEMO 
{ 
class Program 
{ 
    static void Main(string[] args) { 
     var ctx = new DemoContext(); 
     var ord = ctx.Orders.FirstOrDefault(); 
     //. DB should be there now... 
    } 
} 
public class Order 
{ 
public int Id {get;set;} 
public string Code {get;set;} 
public int? QuotationId { get; set; } //optional since it is nullable 
public virtual Quotation Quotation { get; set; } 
    //.... 
} 
public class Quotation 
{ 
public int Id {get;set;} 
public string Code{get;set;} 
// public int? OrderId { get; set; } //optional since it is nullable 
public virtual Order Order { get; set; } 
//... 
} 
public class DemoContext : DbContext 
{ 
    static DemoContext() 
    { 
    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DemoContext>()); 
    } 
    public DemoContext() 
     : base("Name=Demo") { } 
    public DbSet<Order> Orders { get; set; } 
    public DbSet<Quotation> Quotations { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Order>().HasKey(t => t.Id) 
        .HasOptional(t => t.Quotation) 
        .WithOptionalPrincipal(d => d.Order) 
        .Map(t => t.MapKey("OrderId")); // declaring here via MAP means NOT declared in POCO 
     modelBuilder.Entity<Quotation>().HasKey(t => t.Id) 
        .HasOptional(q => q.Order) 
      // .WithOptionalPrincipal(p => p.Quotation) //as both Principals 
      //  .WithOptionalDependent(p => p.Quotation) // as the dependent 
      //   .Map(t => t.MapKey("QuotationId")); done in POCO. 
      ; 
    } 
} 
} 
+0

grazie, la tua risposta mi ha aiutato, ho trovato la risposta corretta e posta. – Masoud

18

Masouds sono:

modelBuilder.Entity<Order>() 
      .HasOptional(o => o.Quotation) 
      .WithOptionalPrincipal() 
      .Map(o => o.MapKey("OrderId")); 

modelBuilder.Entity<Quotation>() 
      .HasOptional(o => o.Order) 
      .WithOptionalPrincipal() 
      .Map(o => o.MapKey("QuotationId")); 

Dà:

enter image description here

Cambiando il codice a :

modelBuilder.Entity<Order>() 
      .HasOptional(o => o.Quotation) 
      .WithOptionalPrincipal(o=> o.Order); 

Dà:

enter image description here

+0

Grazie, questo mi aiuta molto :) –

1
public class OfficeAssignment 
{ 
    [Key] 
    [ForeignKey("Instructor")] 
    public int InstructorID { get; set; } 
    [StringLength(50)] 
    [Display(Name = "Office Location")] 
    public string Location { get; set; } 

    public virtual Instructor Instructor { get; set; } 
} 

l'attributo chiave

C'è un uno-a-zero o uno-relazione tra l'istruttore e l'OfficeAssignment entità. Un incarico ufficio esiste solo in relazione all'istruttore a cui è assegnato, e quindi la sua chiave primaria è anche la sua chiave esterna per l'entità dell'istruttore. Tuttavia, Entity Framework non può riconoscere automaticamente InstructorID come chiave primaria di questa entità poiché il suo nome non segue la convenzione di denominazione ID o classnameID. Pertanto, l'attributo chiave viene utilizzato per identificare come la chiave:

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application