web-dev-qa-db-fra.com

Impossible de déterminer la relation représentée par la propriété de navigation ASP.NET core 2.0 Entity Framework

Je développe actuellement une application ASP.NET qui utilise EntityFramework, pour le code donné

public partial class EnumMeta : Meta
{
    public EnumMeta()
    {
        this.Messages = new HashSet<MessageMeta>();
    }

    public bool IsFlag { get; set; }

    public virtual ICollection<MessageMeta> Messages { get; set; }
}

public partial class MessageMeta : Meta
{
    public MessageMeta()
    {
        this.Enums = new HashSet<EnumMeta>();
        this.Receiver = new HashSet<Module>();
        this.Sender = new HashSet<Module>();
    }

    public int MsgId { get; set; }

    public virtual ICollection<EnumMeta> Enums { get; set; }
    public virtual ICollection<Module> Receiver { get; set; }
    public virtual ICollection<Module> Sender { get; set; }
}

Je reçois une erreur:

Impossible de déterminer la relation représentée par la propriété de navigation "EnumMeta.Messages" de type "ICollection". Soit configurer manuellement la relation, soit ignorer cette propriété en utilisant l'attribut '[NotMapped]' ou en utilisant 'EntityTypeBuilder.Ignore' dans 'OnModelCreating'.

Ce code a été généré automatiquement par EntityFramework à l'aide d'un projet WPF, puis les modèles ont été transférés vers un projet ASP.NET core 2.0 pour effectuer une approche "code-first" de la base de données.

J'ai déjà essayé de configurer [ForeignKey("MessageMeta")] au-dessus de public virtual ICollection<MessageMeta> Messages { get; set; } Sans aucune solution positive.

9
DevTekVE

Comme je l'ai dit plus tôt, il existe de nombreuses différences entre Entity Framework et Entity Framework Core 2.0, Je ne pense pas que vous puissiez simplement prendre les modèles générés à partir de Entity Framework et exécutez Code First avec Entity Framework Core 2.0.

D'après les modèles décrits, il semble que MessageMeta et EnumMeta aient une relation plusieurs-à-plusieurs.

Comme aujourd'hui, Entity Framework Core 2.0 ne prend toujours pas en charge plusieurs-à-plusieurs sans la classe intermédiaire. Donc, pour faire plusieurs à plusieurs dans EF Core 2.0, vous avez besoin de la classe intermédiaire.

MessageMeta

using System.Collections.Generic;

namespace DL.SO.MessageEnum.Web.UI.Models
{
    public class MessageMeta
    {
        public int MsgId { get; set; }

        public List<MessageEnum> EnumMetas { get; set; }
    }
}

EnumMeta

using System.Collections.Generic;

namespace DL.SO.MessageEnum.Web.UI.Models
{
    public class EnumMeta
    {
        public int EnumId { get; set; }
        public bool IsFlag { get; set; }

        public List<MessageEnum> MessageMetas { get; set; }
    }
}

MessageEnum (ou vous pouvez l'appeler EnumMessage) - modèle intermédiaire

namespace DL.SO.MessageEnum.Web.UI.Models
{
    public class MessageEnum
    {
        public int MessageMetaId { get; set; }
        public MessageMeta MessageMeta { get; set; }

        public int EnumMetaId { get; set; }
        public EnumMeta EnumMeta { get; set; }
    }
}

DbContext

using Microsoft.EntityFrameworkCore;

namespace DL.SO.MessageEnum.Web.UI.Models
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options): base(options) { }

        public DbSet<MessageMeta> Messages { get; set; }
        public DbSet<EnumMeta> Enums { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MessageMeta>()
                .HasKey(x => x.MsgId);

            modelBuilder.Entity<EnumMeta>()
                .HasKey(x => x.EnumId);

            modelBuilder.Entity<MessageEnum>()
                .HasKey(x => new { x.MessageMetaId, x.EnumMetaId });
            modelBuilder.Entity<MessageEnum>()
                .HasOne(x => x.MessageMeta)
                .WithMany(m => m.EnumMetas)
                .HasForeignKey(x => x.MessageMetaId);
            modelBuilder.Entity<MessageEnum>()
                .HasOne(x => x.EnumMeta)
                .WithMany(e => e.MessageMetas)
                .HasForeignKey(x => x.EnumMetaId);
        }
    }
}

appsettings.json

{
  "ConnectionStrings": {
    "AppDbConnection": "Data Source=.\\SQLEXPRESS;Initial Catalog=SO.MessageEnum;Integrated Security=True;MultipleActiveResultSets=False;"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

Commencez

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using DL.SO.MessageEnum.Web.UI.Models;
using Microsoft.EntityFrameworkCore;

namespace DL.SO.MessageEnum.Web.UI
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            string dbConnectionString = Configuration.GetConnectionString("AppDbConnection");

            services.AddDbContext<AppDbContext>(options =>
                options.UseSqlServer(dbConnectionString)
            );

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Commandes à exécuter sur Package Manager Console

Add-Migration Init
Update-Database

Base de données générée

enter image description here

11
David Liang