Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No suitable constructor found for entity type MyImage

I'm getting this exception:

System.InvalidOperationException HResult=0x80131509 Message=No suitable constructor found for entity type 'MyImage'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'image' in 'MyImage(string name, string country, Image image)'. Source=Microsoft.EntityFrameworkCore StackTrace: at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConstructorBindingConvention.Apply(InternalModelBuilder modelBuilder) at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder) at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelBuilt(InternalModelBuilder modelBuilder) at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.Validate() at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel() at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator) at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.<>c__DisplayClass5_0.b__1() at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue() at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator) at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_2(IServiceProvider p) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance() at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance() at Microsoft.EntityFrameworkCore.Internal.InternalAccessorExtensions.GetService[TService](IInfrastructure1 accessor) at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor) at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_DatabaseCreator() at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureDeleted() at DigitizedApi.Data.DataInitializer.InitializeData() in D:\School\Webapplicaties IV\DigitizedApi\DigitizedApi\DigitizedApi\Data\DataInitializer.cs:line 27 at DigitizedApi.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, DataInitializer dataInitializer) in D:\School\Webapplicaties IV\DigitizedApi\DigitizedApi\DigitizedApi\Startup.cs:line 103

and I have no clue what the reason could be.

DB context

    public class ApplicationDbContext : IdentityDbContext {

    public DbSet<MyImage> Images { get; set; }
    public DbSet<Visitor> Visitors { get; set; }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options) {
    }

    protected override void OnModelCreating(ModelBuilder builder) {
        base.OnModelCreating(builder);
        builder.ApplyConfiguration(new ImageConfiguration());
        builder.ApplyConfiguration(new VisitorConfiguration());
        builder.ApplyConfiguration(new ImageVisitorConfiguration());
    }
}

Data initializer

        private readonly ApplicationDbContext _dbContext;
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IImageRepository _imageRepository;

    public DataInitializer(ApplicationDbContext context, UserManager<IdentityUser> userManager, IImageRepository imageRepository) {
        _dbContext = context;
        _userManager = userManager;
        _imageRepository = imageRepository;
    }

    //public async Task InitializeData() {
    //    _dbContext.Database.EnsureDeleted();
    //    if (_dbContext.Database.EnsureCreated()) {
    //    }
    //}

    public void InitializeData() {
        _dbContext.Database.EnsureDeleted();//error gets thrown here
        if (_dbContext.Database.EnsureCreated()) {
            //MyImage image1 = new MyImage("Parallax1","France",Image.FromFile("DSC_2544c2.jpg"));
            //_imageRepository.Add(image1);

            _imageRepository.SaveChanges();



        }
    }

    private async Task CreateUser(string email, string password) {
        var user = new IdentityUser { UserName = email, Email = email };
        await _userManager.CreateAsync(user, password);
    }
}

MyImage Class

    public class MyImage {

    #region Fields
    private string _name;
    #endregion

    #region Properties
    public int Id { get; set; }
    [Required]
    public string Name {
        get {
            return _name;
        }

        set {
            if (string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value)) {
                throw new ArgumentException("Name cannot be empty.");
            }
            _name = value;
        }
    }
    public int ISO { get; set; }
    public double ShutterSpeed { get; set; }
    public double Aperture { get; set; }
    public string Country { get; set; }
    public string Content { get; set; }
    #endregion

    #region Constructor
    //public MyImage(string name, int iso, double shutterspeed, double aperture, string country, string content) {
    //    Name = name;
    //    ISO = iso;
    //    ShutterSpeed = shutterspeed;
    //    Aperture = aperture;
    //    Country = country;
    //    Content = content;

    //}

    public MyImage(string name, string country, Image image) {
        Name = name;
        ISO = Convert.ToInt32(Encoding.UTF8.GetString(image.GetPropertyItem(0x8828).Value));
        ShutterSpeed = Convert.ToInt64(Encoding.UTF8.GetString(image.GetPropertyItem(0x9201).Value));
        Aperture = Convert.ToInt32(Encoding.UTF8.GetString(image.GetPropertyItem(0x9202).Value)); ;
        Country = country;
        Content = ConvertImage(image);

    }
    #endregion

    #region Methods
    private string ConvertImage(Image imageToConvert) {
        byte[] Ret;
        try {
            using (MemoryStream ms = new MemoryStream()) {
                imageToConvert.Save(ms, imageToConvert.RawFormat);
                Ret = ms.ToArray();
            }
        } catch (Exception ex) {
            throw;
        }
        return Convert.ToBase64String(Ret);
    }
    #endregion
}

Configuration

    public class ImageConfiguration : IEntityTypeConfiguration<MyImage> {
    public void Configure(EntityTypeBuilder<MyImage> builder) {
        builder.ToTable("Image");

        builder.HasKey(i => i.Id);

        builder.Property(i => i.Name)
            .HasMaxLength(40)
            .IsRequired(true);

        builder.Property(i => i.Country)
            .HasMaxLength(84)
            .IsRequired(true);

        builder.Property(i => i.Content)
            .IsRequired(true);
    }
}

Visitor class

    public class Visitor {

    #region Fields
    private string _name;
    private string _email;
    private string _telephone;
    #endregion

    #region Properties
    public int Id { get; set; }
    public string Name {
        get {
            return _name;
        }
        set {
            if (string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value)) {
                throw new ArgumentException("Name can't be empty.");
            }
            _name = value;
        }
    }

    public string Email {
        get {
            return _email;
        }
        set {
            if (string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value)) {
                throw new ArgumentException("Email can't be empty.");
            }
            Regex regex = new Regex(@"^([a-zA-Z0-9éèà]+[a-zA-Z0-9.-éèàïëöüäîôûêâù]*)@([a-zA-Z]+)[.]([a-z]+)([.][a-z]+)*$");
            Match match = regex.Match(value);
            if (!match.Success) {
                throw new ArgumentException("Email doesn't have a correct format.");
            }
            _email = value;
        }
    }

    public string Telephone {
        get {
            return _telephone;
        }
        set {
            if (string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value)) {
                throw new ArgumentException("Telephone number can't be empty.");
            }
            Regex regex = new Regex(@"(\+(0)?|00)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$");
            Match match = regex.Match(value);
            if (!match.Success) {
                throw new ArgumentException("Telephone number doesn't have a correct format. " +
                    "Please make sure you use an international phone number (+44791112345) and dont forget to add the +.");
            }
            _telephone = value;
        }
    }

    public string Country { get; set; }

    public ICollection<LikedImage> Liked { get; private set; }
    public IEnumerable<MyImage> LikedImages => Liked.Select(i => i.Image);
    #endregion

    #region Constructor
    public Visitor(string name, string email, string telephone, string country = null) {
        Name = name;
        Email = email;
        Telephone = telephone;
        Country = country;
    }
    #endregion
}

Visitor configuration

public class VisitorConfiguration : IEntityTypeConfiguration<Visitor> {
    public void Configure(EntityTypeBuilder<Visitor> builder) {
        builder.ToTable("Visitors");

        builder.HasKey(v => v.Id);

        builder.Property(v => v.Name)
            .HasMaxLength(50)
            .IsRequired(true);

        builder.Property(v => v.Email)
            .HasMaxLength(70)
            .IsRequired(true);

        builder.Property(v => v.Telephone)
            .HasMaxLength(15)
            .IsRequired(true);
    }
}

Intersection table

   public class LikedImage {
    #region Properties
    public int ImageId { get; set; }

    public int VisitorId { get; set; }

    public Visitor Visitor { get; set; }

    public MyImage Image { get; set; }
    #endregion
}

it's configuration

    public class ImageVisitorConfiguration : IEntityTypeConfiguration<LikedImage> {
    public void Configure(EntityTypeBuilder<LikedImage> builder) {
        builder.HasKey(i => new { i.ImageId, i.VisitorId });

        builder.HasOne(i => i.Visitor)
            .WithMany(v => v.Liked)
            .HasForeignKey(i => i.VisitorId);

        builder.HasOne(i => i.Image)
            .WithMany()
            .HasForeignKey(i => i.ImageId);
    }
}

and finally

startup

    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) {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        services.AddDbContext<ApplicationDbContext>(options =>
          options.UseSqlServer(Configuration.GetConnectionString("DigitizedContext")));

        services.AddScoped<DataInitializer>();
        services.AddScoped<IImageRepository, ImageRepository>();
        services.AddScoped<IVisitorRepository, VisitorRepository>();

        services.AddOpenApiDocument(c => {
            c.DocumentName = "apidocs";
            c.Title = "DigitizedAPI";
            c.Version = "v1";
            c.Description = "The DigitizedAPI documentation description.";
            c.DocumentProcessors.Add(new SecurityDefinitionAppender("JWT Token", new SwaggerSecurityScheme {
                Type = SwaggerSecuritySchemeType.ApiKey,
                Name = "Authorization",
                In = SwaggerSecurityApiKeyLocation.Header,
                Description = "Copy 'Bearer' + valid JWT token into field"
            }));
            c.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT Token"));
        });

        services.AddIdentity<IdentityUser, IdentityRole>(cfg => cfg.User.RequireUniqueEmail = true).AddEntityFrameworkStores<ApplicationDbContext>();
        services.Configure<IdentityOptions>(options => {

            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
            options.Lockout.MaxFailedAccessAttempts = 3;
            options.Lockout.AllowedForNewUsers = true;

            options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-._@+";
            options.User.RequireUniqueEmail = true;
        });

        services.AddAuthentication(x => {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(x => {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"])),
                ValidateIssuer = false,
                ValidateAudience = false,
                RequireExpirationTime = true
            };
        });

        //change later to the origen of my site
        services.AddCors(options =>
    options.AddPolicy("AllowAllOrigins", builder => builder.AllowAnyOrigin()
));
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, DataInitializer dataInitializer) {
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        } else {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseAuthentication();

        app.UseMvc();

        app.UseSwaggerUi3();
        app.UseSwagger();

        app.UseCors("AllowAllOrigins");

        //dataInitializer.InitializeData().Wait();
        dataInitializer.InitializeData();
    }
}

I'm very sorry, I know it's a lot of code but I'm a student and my teacher has kind of forsaken us and we need to find things out on our own and I wouldn't know what could be wrong.

Thanks in advance!

like image 562
Mout Pessemier Avatar asked Jan 26 '23 13:01

Mout Pessemier


1 Answers

EF.Core calls entity constructors internally, so EF.Core should somehow determine what to pass as parameter. EF.Core < 2.1 wasn't able to inject parameters at all, but starting from EF.Core 2.1 it is possible - if all parameters have same names as properties, EF.Core uses properties values as parameters values (see docs for more info):

Starting with EF Core 2.1, it is now possible to define a constructor with parameters and have EF Core call this constructor when creating an instance of the entity. The constructor parameters can be bound to mapped properties, or to various kinds of services to facilitate behaviors like lazy-loading.

In your case it's not possible to parse Image image parameter (EF.Core 2.1, older EF.Core won't work at all), so simple solution is to add default constructor to your MyImage class.

like image 139
ingvar Avatar answered Jan 29 '23 03:01

ingvar