web-dev-qa-db-fra.com

Implémentation de la relation Zero Or One à Zero Or One dans EF Code d'abord par Fluent API

J'ai deux cours POCO

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

chaque commande peut être faite à partir d'une ou de zéro cotation, et chaque cotation peut provoquer une commande, j'ai donc une relation "un ou zéro" à "un ou zéro", comment puis-je implémenter cela, dans EF Code d'abord par une API fluide?

34
Masoud

En changeant les pocos en:

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

et en utilisant ces fichiers de mappage:

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

nous aurons ce DB (cela signifie 0..1-0..1):

enter image description here

avec des remerciements particuliers à ( M. Vahid Nasiri )

37
Masoud

La procédure de @ Masoud était:

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

Il donne:

enter image description here

En changeant le code en:

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

Il donne:

enter image description here

25

Voir http://msdn.Microsoft.com/en-us/data/jj59162 Relations EF

Un excellent livre http://my.safaribooksonline.com/book/-/9781449317867

Voici un article du développeur de décembre 2010. Mais toujours pertinent http://social.msdn.Microsoft.com/Forums/uk/adonetefx/thread/aed3b3f5-c150-4131-a686-1bf547a68804 The l'article ci-dessus est un bon résumé ou les combinaisons possibles ici.

Une solution où la table dépendante a la clé de la table primaire est possible.

Si vous voulez des clés indépendantes où les deux sont des principaux dans un scénario PK/FK, je ne pense pas que vous pouvez le faire dans Code d'abord avec Fluent API. S'ils partagent une clé, vous êtes OK. 1: 1 facultatif suppose que la personne à charge utilise la clé du primaire.

Mais puisque vous devez enregistrer l'une des tables avant l'autre. Vous pouvez vérifier l'une des clés étrangères avec le code. OR ajoutez le deuxième étranger à la base de données une fois que le code l'a créé.

Vous vous rapprocherez. Mais EF se plaindra de conflits de clés étrangères si vous voulez que les deux soient des clés étrangères. Essentiellement, le A dépend de B dépend A EF n'aime pas, même si les colonnes sont nullables et techniquement possible sur la base de données.

Ici, utilisez ce programme de test pour l'essayer. Il suffit de commenter le contenu de l'API Fluent pour essayer certaines options. Je n'ai PAS pu faire fonctionner EF5.0 avec INDEPENDENT PK/FK 0: 1 à 0: 1 Mais bien sûr, il y a des compromis raisonnables comme discuté.

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.
            ;
    }   
}
}
6
phil soady

Adapté de cela réponse , essayez ceci.

Tout d'abord, corrigez vos cours:

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
}

Ensuite, utilisez l'API couramment comme ça:

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

Fondamentalement, pour les relations 1: 1 ou [0/1]: [0/1], EF a besoin que les clés primaires soient partagées.

5
Moritz
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'attribut clé

Il existe une relation un à zéro ou un entre l'instructeur et les entités OfficeAssignment. Une affectation de bureau n'existe que par rapport à l'instructeur auquel elle est affectée, et donc sa clé primaire est également sa clé étrangère pour l'entité Instructeur. Mais Entity Framework ne peut pas reconnaître automatiquement InstructorID comme clé primaire de cette entité car son nom ne suit pas la convention de dénomination ID ou classnameID. Par conséquent, l'attribut Key est utilisé pour l'identifier en tant que clé:

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

1
astro8891