I have a model Blueprint
that requires a reference to an IdentityUser. When I run Add-Migration CreateBlueprintSchema
the following error is thrown:
No suitable constructor was found for entity type 'Blueprint'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'author' in 'Blueprint(IdentityUser author, string name, string data)'.
How do I resolve this issue?
Blueprint.cs
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;
namespace FactorioStudio.Models
{
public class Blueprint
{
[MaxLength(40)]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Data { get; set; }
[Required]
public IdentityUser Author { get; set; }
[Required]
public DateTime CreationDate { get; set; }
public Blueprint? ParentBlueprint { get; set; }
public Blueprint(IdentityUser author, string name, string data)
{
Author = author;
Name = name;
Data = data;
CreationDate = DateTime.UtcNow;
string hashSource = Author.Id
Name
CreationDate.ToString("s", System.Globalization.CultureInfo.InvariantCulture)
Data;
using SHA1 sha1 = SHA1.Create();
byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(hashSource));
string hash = BitConverter.ToString(hashBytes).Replace("-", String.Empty).ToLower();
Id = hash;
}
}
}
CodePudding user response:
change your model like this:
public class Blueprint
{
[MaxLength(40)]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Data { get; set; }
[Required]
public IdentityUser Author { get; set; } = new IdentityUser();
//.......
}
or just add a non-parameter constructor
in your model.
CodePudding user response:
Like I wrote in comment, EF Core cannot set navigation properties using a constructor. Instead, use a custom value generator.
public class BlueprintHashGenerator : ValueGenerator<string>
{
public override bool GeneratesTemporaryValues => false;
public override string Next(EntityEntry entry)
{
if (entry.Entity is not Blueprint bp)
{
throw new ApplicationException("Unexpected entity");
}
string hashSource = bp.Author.Id
bp.Name
bp.CreationDate.ToString("s", System.Globalization.CultureInfo.InvariantCulture)
bp.Data;
using SHA1 sha1 = SHA1.Create();
byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(hashSource));
return BitConverter.ToString(hashBytes).Replace("-", String.Empty).ToLower();
}
}
then in model builder
builder.Entity<Blueprint>().Property(bp => bp.Id).HasValueGenerator<BlueprintHashGenerator>().ValueGeneratedNever();
It will generate the value on SaveChanges
, so ensure all properties are set before calling save (Author
, Name
, CreationDate
, Data
).