0

J'ai deux classes d'un utilisateur et une table d'image:EF Code d'abord, comment pouvez-vous mapper une relation bidirectionnelle un à un ou zéro dans EF?

public class User 
{ 
    public Guid? ImageId {get; set;} 
    public Image Image {get; set;} 
} 

public class Image 
{ 
    public Guid? UserId {get; set;} 
    public User User {get; set;} 
} 

L'utilisateur et l'image peuvent exister sur leur propre sans l'autre entité, mais s'ils ont une relation, un utilisateur ne peut être associé avec une image, et une image ne peut avoir d'utilisateur que si elles ne sont pas nulles. Comment est-ce que je cartographie ceci? Actuellement, j'ai:

public UserMapping() 
    {    
     HasOptional(x => x.ProfileImage).WithOptionalPrincipal(x => 
     x.User).Map(x => x.MapKey("UserId")); 
    } 

Et rien sur le ImageMapping depuis d'autres réponses, il a été déclaré ne pas la carte relation deux fois ou il disjoncte. Cependant, le fichier de migration finit par générer une propriété user_id supplémentaire sur la table d'image puis:

CreateTable(
      "dbo.Images", 
      c => new 
       { 
        Id = c.Guid(nullable: false), 
        UserId = c.Guid(), 
        User_Id = c.Guid(), 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.Users", t => t.User_Id) 
      .Index(t => t.User_Id); 

Ce qui est faux. Comment puis-je faire le mappage de manière appropriée?

EDIT: J'ai également trouvé thishttp: //stackoverflow.com/questions/21082085/entity-framework-optional-1-to-1-relation-on-both-ends et essayé ce qui est montré dans l'original question qui prétend travailler, mais il ne crée pas encore User_Id.

+0

Pas une réponse à la mais je crois que si vous le nom user_id lors du mappage de la clé, il va se débarrasser du double. Sauf si vous créez directement UserId dans l'utilisateur, je crois que par défaut User_Id – Ronan

+0

Je le fais comme vu ci-dessus.Et déclarant explicitement cette propriété en tant que clé dans le mappage. – SventoryMang

+0

Dans le code ci-dessus, vous ne créez pas de champ UserId. Lorsque vous l'omettez, l'infrastructure d'entité crée User_Id à la place. Dans la cartographie vous avez alors UserId qui ne correspond pas au nom de l'ef créé celui qui est User_Id – Ronan

Répondre

0

Regardez this page pour plus de détails.

Fondamentalement, une relation un à un est celle dans laquelle le PK de l'entité principale passe PK et FK dans l'entité dépendante. Pour autant que je puisse voir ici, vous devez mapper deux entités comme optionnelles entre elles et ce n'est pas vraiment possible dans EF, du moins pas comme One to Zero-Or-One.

Je comprends que vous voulez que les deux parties soient optionnelles mais il s'avère que EF doit savoir laquelle de vos entités est la principale. Donc, voici un moyen de changer les relations. Je vous suggère de définir votre entité principale dans la relation et l'autre devient facultative. Par exemple:

utilisateur comme le principal:

//Your entities 
public class Image 
{ 
    public Guid UserId { get; set; } 

    public virtual User User { get; set; } 
} 

public class User 
{ 
    public Guid UserId { get; set; } 

    public virtual Image Image { get; set; } 
} 

//Mappings: 
public class ImageMappingConfiguration : EntityTypeConfiguration<Image> 
    { 
     public ImageMappingConfiguration() 
     { 
      HasKey(x => x.UserId); 
     } 
    } 

public class UserMappingConfiguration : EntityTypeConfiguration<User> 
    { 
     public UserMappingConfiguration() 
     { 
      HasKey(x => x.UserId); 

      HasOptional(x => x.Image) 
       .WithRequired(x => x.User); 
     } 
    } 

Vous obtiendrez ceci après add-migration:

public override void Up() 
{ 
    CreateTable(
      "dbo.Images", 
      c => new 
      { 
       UserId = c.Guid(nullable: false) 
      }) 
     .PrimaryKey(t => t.UserId) 
     .ForeignKey("dbo.Users", t => t.UserId) 
     .Index(t => t.UserId); 

    CreateTable(
      "dbo.Users", 
      c => new 
      { 
       UserId = c.Guid(nullable: false) 
      }) 
     .PrimaryKey(t => t.UserId); 
} 

Voir la clé primaire de l'utilisateur passant comme PK et FK à l'image? C'est ainsi que EF gère les relations One to Zero-Or-One.

After update-database:

MISE A JOUR! Deux relations un-à-plusieurs avec des contraintes uniques.

Essayons cette approche. Faites-moi savoir si cela fonctionne pour vous.

public sealed class Image 
{ 
    public Image() 
    { 
     Users = new List<User>(); 
    } 

    public Guid Id { get; set; } 

    public Guid? UserId { get; set; } 

    public List<User> Users { get; set; } 

    public User User { get; set; } 
} 

public sealed class User 
{ 
    public User() 
    { 
     Images = new List<Image>(); 
    } 

    public Guid Id { get; set; } 

    public Guid? ImageId { get; set; } 

    public List<Image> Images { get; set; } 

    public Image Image { get; set; } 
} 

//Mappings: 
public class ImageMappingConfiguration : EntityTypeConfiguration<Image> 
{ 
    public ImageMappingConfiguration() 
    { 
     HasKey(x => x.Id); 

     Property(x => x.UserId) 
      .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute("IX_ImageMustBeUnique") 
      { 
       IsUnique = true 
      })); 


     HasMany(x => x.Users) 
      .WithOptional(x => x.Image) 
      .HasForeignKey(x => x.ImageId) 
      .WillCascadeOnDelete(true); 
    } 
} 

public class UserMappingConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserMappingConfiguration() 
    { 
     HasKey(x => x.Id); 

     Property(x => x.ImageId) 
      .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute("IX_UserMustBeUnique") 
      { 
       IsUnique = true 
      })); 

     HasMany(x => x.Images) 
      .WithOptional(x => x.User) 
      .HasForeignKey(x => x.UserId); 
    } 
} 

Utilisation:

//test adding a user and an image. 
var user = new User 
{ 
    Id = Guid.NewGuid(), 
}; 
var image = new Image 
{ 
    Id = Guid.NewGuid(), 
}; 

using (var ctx = new Context()) 
{ 
    ctx.Users.Add(user); 
    ctx.Images.Add(image); 
    ctx.SaveChanges(); 

    //associate them 
    user.Images.Add(image); 
    image.Users.Add(user); 
    ctx.SaveChanges(); 

    //try to add a second image to the user 
    var image2 = new Image 
    { 
     Id = Guid.NewGuid() 
    }; 

    try 
    { 
     user.Images.Add(image2); 
     ctx.SaveChanges(); 
    } 
    catch (DbUpdateException ex) 
    { 
     Console.WriteLine(ex); 
    } 
} 
+0

J'ai marqué votre réponse, car il semble être la chose la plus proche, malheureusement, je ne peux pas avoir un principal et un dépendant, les deux peuvent exister individuellement. Il semble donc que ce n'est pas possible dans la configuration de base de données normale de toute façon. – SventoryMang

+0

Yeap. On dirait que c'est le cas. Avez-vous essayé de créer deux relations un-à-plusieurs et de définir des contraintes uniques? Le contre c'est que vous aurez des listes d'Utilisateur et d'Image mais je pense que ça pourrait marcher. –

+0

Pouvez-vous donner un exemple ou modifier votre réponse? Je ne suis pas contre deux un à plusieurs, mais alors comment faites-vous la contrainte unique? – SventoryMang