This is my program class where the migration is going to start
public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
try{
var context = services.GetRequiredService<DataContext>();
await context.Database.MigrateAsync();
await Seed.SeedUsers(context);
}catch(Exception ex){
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex,"An error occurred during migration");
}
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
This is my main class
public class AppUser
{
public int Id { get; set; }
[StringLength(20)]
public string UserName { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
public DateTime DateOfBirth { get; set; }
public DateTime Created { get; set; }=DateTime.Now;
public DateTime LastActive { get; set; }=DateTime.Now;
public string Gender { get; set; }
public string City { get; set; }
public string Country { get; set; }
public ICollection<Photo> Photos { get; set; }
public UserCard Cards { get; set; }
public int GetAge(){
return DateOfBirth.CalculateAge();
}
}
And this is the UserCard that i want to be linked with AppUser in the DataBase
[Table("Cards")]
public class UserCard
{
public int Id { get; set; }
public string Code { get; set; }
public string Status { get; set; }
public string Type { get; set; }
public AppUser AppUser{ get; set; }
public int AppUserId { get; set; }
}
Here is how my seed function is looking
public class Seed
{
public static async Task SeedUsers(DataContext context){
if(await context.Users.AnyAsync()) return;
var userData=await System.IO.File.ReadAllTextAsync("Data/UserSeedData.json");
var users=JsonSerializer.Deserialize<List<AppUser>>(userData);
foreach (var user in users)
{
using var hmac=new HMACSHA512();
user.UserName = user.UserName.ToLower();
user.PasswordHash=hmac.ComputeHash(Encoding.UTF8.GetBytes("admin"));
user.PasswordSalt=hmac.Key;
context.Users.Add(user);
}
await context.SaveChangesAsync();
}
And this is the data that i want to put in the database.Here i have another class Photos that is why it is there
[
{
"UserName": "Tami",
"Gender": "female",
"DateOfBirth": "1995-09-28",
"Created": "2020-05-01",
"LastActive": "2020-05-29",
"City": "Haring",
"Country": "San Marino",
"Photos": [
{
"Url": "https://randomuser.me/api/portraits/women/94.jpg",
"IsMain": true
}
],
"Cards": [
{
"Code": "123123543",
"Status": "notActive",
"Type": "default"
}
]
}
]
When I enter: dotnet watch run my database is going to create the tables correctly with the right linking but when the seed is happening I get this error
fail: API.Program[0]
An error occurred during migration
System.Text.Json.JsonException: The JSON value could not be converted to Entities.UserCard. Path: $[0].Cards | LineNumber: 15 | BytePositionInLine: 18.
at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
at API.Data.Seed.SeedUsers(DataContext context) in C:\Users\Alejandro\Desktop\ProjectApp\API\Data\Seed.cs:line 19
at API.Program.Main(String[] args) in C:\Users\Alejandro\Desktop\ProjectApp\API\Program.cs:line 24
I found the problem
public ICollection<Photo> Photos { get; set; }
public UserCard Cards { get; set; }
I just needed to put ICollection to the Cards prop but I need help to solve this .Now with ICollection the relation is one to many but for cards I want the relation to be 1 to 1 what do I need to do in this case?
CodePudding user response:
For 1 to 1 relation, you may change the json structure like this;
[
{
...
"Cards": {
"Code": "123123543",
"Status": "notActive",
"Type": "default"
}
...
}
]
Notice that Cards property is now an object, rather than an array.