web-dev-qa-db-fra.com

Fractionnement de table d'entité cadre: pas dans la même hiérarchie de types/ne pas avoir une relation de clé étrangère un à un valide

J'utilise Entity Framework 6 avec une approche Code-First et je souhaite que deux entités soient placées dans le même tableau. Qu'est-ce que je fais mal?

[Table("Review")]
public class Review
{
    public int Id { get; set; }
    public PictureInfo PictureInfo { get; set; }
    public int PictureInfoId { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key, ForeignKey("Review")]
    public int ReviewId { get; set; }
    public Review Review { get; set; }
}

L'erreur que j'obtiens: Les types d'entité 'PictureInfo' et 'Review' ne peuvent pas partager la table 'Review' car elles ne font pas partie de la même hiérarchie de types ou n'ont pas de relation de clé étrangère un à un valide avec les clés primaires correspondantes clés entre eux.

Qu'est-ce que je fais mal?

14
Andrew

On dirait que le problème est que la relation a été interprétée comme un-à-0..1 au lieu d'un à un.

La clé étrangère int PictureInfoId à la fin de la révision étant inutile/ignorée, sa non-nullabilité n'a pas rendu la fin de la relation dans la relecture requise. La suppression de cette clé inutile et l'ajout de l'attribut [Obligatoire] à la propriété de navigation PictureInfo ont résolu le problème.

Voici la classe Review corrigée.

[Table("Review")]
public class Review
{
    public int Id { get; set; }
    [Required]
    public PictureInfo PictureInfo { get; set; }
}
5
Andrew

J'ai réussi à réaliser ce que vous vouliez avec une api fluide. Fluent api offre des options de configuration beaucoup plus riches que les annotations de données. J'ai un peu changé vos classes d'entités:

public class Review
{
    public int Id { get; set; }
    public PictureInfo PictureInfo { get; set; }
}

La propriété PictureInfoId n'est pas nécessaire car la relation de clé étrangère sera établie sur les clés primaires des deux entités.

public class PictureInfo
{
    public int Id { get; set; }
    public Review Review { get; set; }
}

Étant donné que Review et PictureInfo seront mappés sur la même table, ils doivent partager la même colonne de clé primaire. Par conséquent, pour PictureInfo et Review, cette colonne doit avoir le même nom. Si vous souhaitez conserver dans la propriété de clé primaire PictureInfo nommée ReviewId, vous pouvez le faire, mais vous devez ensuite mapper son nom sur "Id". Enfin, le DbContext:

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Review>().HasKey( e => e.Id );
        modelBuilder.Entity<Review>()
            .HasRequired(e => e.PictureInfo)
            .WithRequiredDependent(e => e.Review);
        modelBuilder.Entity<Review>().Map(m => m.ToTable("Review"));
        modelBuilder.Entity<PictureInfo>().Map(m => m.ToTable("Review"));
        modelBuilder.Entity<PictureInfo>().HasKey(e => e.Id);

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Review> Reviews { get; set; }
    public DbSet<PictureInfo> PictureInfos { get; set; }
}

OnModelCreating contient une définition de mappage api fluide. Tout ce que vous avez à faire est de définir des clés primaires sur les deux entités portant le même nom, de lier ces deux entités avec une relation 1-1, puis de les mapper à la même table.

6
mr100

L'autre moyen de résoudre ce problème consiste à créer une vue contenant uniquement les champs souhaités. Mappez ensuite l'entité sur la vue.

1
Greg Gum
using System.Linq;
using System.Data.Entity;
namespace Sample
{

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new EmployeeDBContext())
            {
                var result = context.Set<Employee>().Include(x => x.Department).ToArray();
            }
        }
    }

    public class EmployeeDBContext : DbContext
    {
        public EmployeeDBContext() : base("EmployeeDB") { }

        public DbSet<Employee> Employee { get; set; }
        public DbSet<Department> Department { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Department>().ToTable("Departments").HasKey(x => x.DepartmentId);
            modelBuilder.Entity<Employee>().ToTable("Employees").HasKey(x => x.Id);
            //ForeignKey mapping 
            modelBuilder.Entity<Employee>().HasRequired(x => x.Department).WithMany().HasForeignKey(x => x.DepartmentId);
            base.OnModelCreating(modelBuilder);
        }
    }

    //Domain Entity
    public class Employee
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Department Department { get; set; }
        public int DepartmentId { get; set; }
    }

    //Domain Entity
    public class Department
    {
        public int DepartmentId { get; set; }
        public string DepartmentName { get; set; }
    } 
}
0
Code First

(Ces tests et erreurs ont été écrits par rapport à EF 6.1.3)

Premier essai

[Table("Review")]
public class Review
{
    [Key]
    public int Id { get; set; }
    public PictureInfo PictureInfo { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key]
    public int Id { get; set; }
    public Review Review { get; set; }
}

Avec les entités ci-dessus, j'ai reçu cette erreur:

Impossible de déterminer la fin principale d'une association entre les types . L'extrémité principale de cette association doit être explicitement Configurée à l'aide de la relation API couramment utilisée ou des annotations data .

Deuxième essai

[Table("Review")]
public class Review
{
    [Key]
    public int Id { get; set; }

    [Required]
    public PictureInfo PictureInfo { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key]
    public int Id { get; set; }

    [Required]
    public Review Review { get; set; }
}

Les types d'entité 'Review' et 'PictureInfo' ne peuvent pas partager la table 'Review', car ils ne font pas partie de la même hiérarchie de types ou n'ont pas Une relation de clé étrangère valide avec un correspondant. clés entre eux.

Troisième tentative

[Table("Review")]
public class Review
{
    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("Id")]
    public PictureInfo PictureInfo { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("Id")]
    public Review Review { get; set; }
}

Impossible de déterminer la fin principale d'une association entre les types . L'extrémité principale de cette association doit être explicitement Configurée à l'aide de la relation API couramment utilisée ou des annotations data .

Code de travail

[Table("Review")]
public class Review
{
    [Key, ForeignKey("PictureInfo")]
    public int Id { get; set; }

    public PictureInfo PictureInfo { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key, ForeignKey("Review")]
    public int Id { get; set; }

    public Review Review { get; set; }
}
0
Mark Rucker