Tengo una relación de muchos a muchos entre Post y Tag, representada por la entidad unir PostTag. Actualmente puedo acceder a la tabla PostTag en mi vista Details de la clase Post; Por ejemplo, puedo ver un Post en particular y mostrar el asociado PostTags. Sin embargo, solo he podido mostrar las propiedades PostTag y PostId y {{x10}}, mientras me gustaría mostrar propiedades relacionadas con la clase {{x11}} a través del {{x12 }} entidad.

Hay varios posts detallando en línea las formas de mostrar relaciones de muchos a muchos, pero ellos Todos parecen ser ampliamente diferentes al enfoque que he tomado, y por lo tanto, no parecen ser fácilmente traducibles a mi proyecto.

Modelos

public class Post
    {
        public int Id { get; set; } // primary key
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime PublicationDate { get; set; }

        public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
    }

public class Tag
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }

        public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
    }

public class PostTag
    {
        public int PostId { get; set; }
        public Post post { get; set; }

        public int TagId { get; set; }
        public Tag tag { get; set; }
    }

parte relevante del postscontroller

public class PostsController : Controller
    {
        private readonly Website.Data.ApplicationDbContext _context;

        public PostsController(Website.Data.ApplicationDbContext context)
        {
            _context = context;
        }
        // GET: Post/Details/5
        public async Task<IActionResult> Details([Bind(Prefix = "Id")]int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var post = await _context.Post
                .Include(p => p.Author)
                .Include(p => p.PostTags)
                .FirstOrDefaultAsync(m => m.Id == id);
            if (post == null)
            {
                return NotFound();
            }

           return View(post);
        }
    }

db contexto

public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
        public DbSet<Author> Author { get; set; }
        public DbSet<Post> Post { get; set; }
        public DbSet<Tag> Tag { get; set; }
        public DbSet<PostTag> PostTag { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<PostTag>()
                .HasKey(t => new { t.PostId, t.TagId });
        }
    }

Ver

@model Website.Models.Post
@foreach (var postTag in Model.PostTags)
{
<tr>
    <td>
        @Html.DisplayFor(modelItem => postTag)
    </td>
</tr>
}

Esta vista muestra el PostTags asociado con un Post} en particular. Por ejemplo, en https://localhost:xxxxx/Posts/Details/1, se accede a Post con Id == 1, y se muestran su Tags asociado.

PostId
1
TagId
2
PostId
1
TagId
4
PostId
1
TagId
5

Parece que no puedo acceder a Tag.Title; Por ejemplo, @Html.DisplayFor(modelItem => postTag.tag.Title) no muestra ninguna vista. Mi salida deseada sería, suponiendo que Tag filas de Fiction, Nonfiction y Classic. Id Los valores iguales a 2, 4, {{x8} } y 5,

Fiction
Nonfiction
Classic

Aprecie cualquier consejo aquí.

Editar: Al cargar la página Detalles en modo de depuración, la variable post contiene todas las propiedades esperadas que incluyen PostTags. PostTags contiene el número esperado de elementos (tres {PostTag elementos porque esta instancia Post tiene tres asociadas Tags). Cada elemento contiene propiedades de PostId, TagId, post y tag; Sin embargo, {{x10}} es {{x11}}. Este es el tema, ya que estoy tratando de acceder a {{x12}}. Captura de pantalla de las variables locales a continuación:

local variables

0
heds1 15 jul. 2019 a las 11:13

1 respuesta

La mejor respuesta

Puede incluir múltiples niveles de datos relacionados utilizando Entonces enclice el método .

var post= await _context.Post
                        .Include(p => p.Author)
                        .Include(p => p.PostTags)
                        .ThenInclude(pt => pt.Tag)
                        .FirstOrDefaultAsync(p => p.Id == id);

DBContext muchos a muchos:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(builder);
    modelBuilder.Entity<PostTag>()
        .HasKey(pt => new { pt.PostId, pt.TagId });

    modelBuilder.Entity<PostTag>()
        .HasOne(pt => pt.Post)
        .WithMany(p => p.PostTags)
        .HasForeignKey(pt => pt.PostId);

    modelBuilder.Entity<PostTag>()
        .HasOne(pt => pt.Tag)
        .WithMany(t => t.PostTags)
        .HasForeignKey(pt => pt.TagId);
}

Consulte https: //docs.microsoft.com/en-us/ef/core/modeling/relationships?view=aspnetcore-2.1#Otros--Relacioneship-Patterns

2
Ryan 16 jul. 2019 a las 06:13