C
C#•3mo ago
Lamar

Entity Framework Core 8 -Foreign Key Constraint failure.

Hello, I am playing around with EF code first and I am trying to model 3 tables:
Product newProduct = new()
{
Id = guid,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
Name = ProductNutritionModel.Product.Name,
Weight = 10,
IsVegan = false,
IsVegetarian = false,
Rating = Random.Shared.Next(1, 10),
NutritionalValue = new NutritionalValue
{
EnergeticValue = 10,
Fat = 50,
SaturatedFats = 30,
Carbohydrate = 40,
Sugar = 20,
Protein = Random.Shared.Next(15, 100),
Salt = Random.Shared.Next(12, 100),
ProductId = guid
}
};

if (existingDNI is not null)
{
existingDNI.Products.Add(newProduct);
foreach (var existingDniProduct in existingDNI.Products)
{
existingDniProduct.DailyNutritionInfoId = existingDniProduct.Id;
}

var saveResult = await DbContext.SaveChangesAsync();
if (saveResult > 0)
{
Navigation.NavigateTo("");
}
}
else
{
DailyNutritionInfo newDailyNutritionInfo = new()
{
Id = Guid.NewGuid(),
CreatedAt = DateTime.Today,
Products = [newProduct],
};

DbContext.DailyNutritionInfos.Add(newDailyNutritionInfo);

var result = await DbContext.SaveChangesAsync();
if (result > 0)
{
Navigation.NavigateTo("");
}
}
Product newProduct = new()
{
Id = guid,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
Name = ProductNutritionModel.Product.Name,
Weight = 10,
IsVegan = false,
IsVegetarian = false,
Rating = Random.Shared.Next(1, 10),
NutritionalValue = new NutritionalValue
{
EnergeticValue = 10,
Fat = 50,
SaturatedFats = 30,
Carbohydrate = 40,
Sugar = 20,
Protein = Random.Shared.Next(15, 100),
Salt = Random.Shared.Next(12, 100),
ProductId = guid
}
};

if (existingDNI is not null)
{
existingDNI.Products.Add(newProduct);
foreach (var existingDniProduct in existingDNI.Products)
{
existingDniProduct.DailyNutritionInfoId = existingDniProduct.Id;
}

var saveResult = await DbContext.SaveChangesAsync();
if (saveResult > 0)
{
Navigation.NavigateTo("");
}
}
else
{
DailyNutritionInfo newDailyNutritionInfo = new()
{
Id = Guid.NewGuid(),
CreatedAt = DateTime.Today,
Products = [newProduct],
};

DbContext.DailyNutritionInfos.Add(newDailyNutritionInfo);

var result = await DbContext.SaveChangesAsync();
if (result > 0)
{
Navigation.NavigateTo("");
}
}
I can add 1 Product entity to the DailyNutrition collection, but if I try to add more I am getting the "Foreign Key Constraint" error. To be honest it's unclear to me which FK is referring to.
No description
No description
No description
48 Replies
FusedQyou
FusedQyou•3mo ago
The error would specify what the actual missing constraint is
Lamar
Lamar•3mo ago
Could you tell me where to look for this? I will paste screenshots where i've been looking for:
No description
No description
leowest
leowest•3mo ago
well the way u made it, its one to one
Lamar
Lamar•3mo ago
You mean Product - NutritionalValue? DailyInfo - Product I hope its one to many Will take a look in a bit
leowest
leowest•3mo ago
Well what ur saying is that X should accept more than one of Y And at least from the 3 models u provided I did not see anything that would allow for that
Lamar
Lamar•3mo ago
Shouldn't DailyInfo have a collection of Products. And in turn each product shold have 1 NutritionalValue reference
leowest
leowest•3mo ago
if DailyNutrition is supposed to accept multiple products then yes its what composes a one to many https://learn.microsoft.com/en-us/ef/core/modeling/relationships/one-to-many
Lamar
Lamar•3mo ago
Yes, that's how I wanted it to be. I will remove the reference to the related entity and test how that works out, should be fine since there are only 2 It seems it's related to the DailyNutritionInfo - Product relationship
leowest
leowest•3mo ago
well u have to remove/update the migration with the updates or modify the table ofc that depends how ur doing it dbfirst or codefirst
Lamar
Lamar•3mo ago
I am doing it codefirst, I've been dropping the db and creating a fresh migration for each change
leowest
leowest•3mo ago
sure, can you $paste your models to the below site?
MODiX
MODiX•3mo ago
If your code is too long, you can post to https://paste.mod.gg/ and copy the link into chat for others to see your shared code!
leowest
leowest•3mo ago
or if u got it working just ignore it 😛
Lamar
Lamar•3mo ago
Will do, I didnt get to make it to work yet
Lamar
Lamar•3mo ago
BlazeBin - nhjclnsxalbs
A tool for sharing your source code with the world!
Lamar
Lamar•3mo ago
Should I also paste the code where I am trying to create these entities? Maybe I am doing something wrong there
Lamar
Lamar•3mo ago
BlazeBin - tzuvdmmgkyir
A tool for sharing your source code with the world!
leowest
leowest•3mo ago
that cuts me the job of doing it my self to test so thx
Lamar
Lamar•3mo ago
Thanks a lot btw. I guess I can just paste the whole component. Will update
Lamar
Lamar•3mo ago
BlazeBin - tcaeoqnibbqx
A tool for sharing your source code with the world!
leowest
leowest•3mo ago
public class Product
{
public Guid Id { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
[MaxLength(100)]
public required string Name { get; set; }
public double Weight { get; set; }
public bool IsVegan { get; set; }
public bool IsVegetarian { get; set; }
public int Rating { get; set; }
public Guid DailyNutritionInfoId { get; set; }
public DailyNutritionInfo DailyNutritionInfo { get; set; } = null!;
}

public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.HasOne(x => x.DailyNutritionInfo)
.WithMany(n => n.Products)
.HasForeignKey(x => x.DailyNutritionInfoId);
}
}

public class DailyNutritionInfo
{
public Guid Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public ICollection<Product> Products { get; set; } = = null!;
}
public class Product
{
public Guid Id { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
[MaxLength(100)]
public required string Name { get; set; }
public double Weight { get; set; }
public bool IsVegan { get; set; }
public bool IsVegetarian { get; set; }
public int Rating { get; set; }
public Guid DailyNutritionInfoId { get; set; }
public DailyNutritionInfo DailyNutritionInfo { get; set; } = null!;
}

public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.HasOne(x => x.DailyNutritionInfo)
.WithMany(n => n.Products)
.HasForeignKey(x => x.DailyNutritionInfoId);
}
}

public class DailyNutritionInfo
{
public Guid Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public ICollection<Product> Products { get; set; } = = null!;
}
it would be something like this
Lamar
Lamar•3mo ago
But this way there will be a one to many between products and NutritinalValue
leowest
leowest•3mo ago
ah my bad u want it to DailyNutrition the idea is the same
Lamar
Lamar•3mo ago
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<DailyNutritionInfo>()
.HasMany(d => d.Products)
.WithOne(p => p.DailyNutritionInfo)
.HasForeignKey(p => p.DailyNutritionInfoId).IsRequired();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<DailyNutritionInfo>()
.HasMany(d => d.Products)
.WithOne(p => p.DailyNutritionInfo)
.HasForeignKey(p => p.DailyNutritionInfoId).IsRequired();
}
I have added this, but it behaves the same
leowest
leowest•3mo ago
but wasn't the issue that u were trying to add more than one nutritionvalue to products rrr products to nutrition value*
Lamar
Lamar•3mo ago
No it's the other way around I can add 1 product to a dailyNutritonalInfo But when I try to add more I get that fk issue I have completely commeted out and made a migration without the nutritional value part
leowest
leowest•3mo ago
ok let me update sec updated the above
Lamar
Lamar•3mo ago
It's the way I have it also I guess this means I am not creating it properly in blazor
leowest
leowest•3mo ago
that should work, let me give it atry works for me
Lamar
Lamar•3mo ago
well Could you share how you created the entities before saving them?
leowest
leowest•3mo ago
ah ok I see the problem u should not set the id the db sets it mm unsure if sqlite handles guid thou
Lamar
Lamar•3mo ago
Which one? On the Product? Or on each product for the DailyNutrition FK?
leowest
leowest•3mo ago
Product newProduct = new()
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
Name = $"Product {id}",
Weight = Random.Shared.Next(2, 10),
IsVegan = Random.Shared.Next(0, 2) == 1,
IsVegetarian = Random.Shared.Next(0, 2) == 1,
Rating = Random.Shared.Next(1, 10),
DailyNutritionInfo = new DailyNutritionInfo
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow
}
};
Product newProduct = new()
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
Name = $"Product {id}",
Weight = Random.Shared.Next(2, 10),
IsVegan = Random.Shared.Next(0, 2) == 1,
IsVegetarian = Random.Shared.Next(0, 2) == 1,
Rating = Random.Shared.Next(1, 10),
DailyNutritionInfo = new DailyNutritionInfo
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow
}
};
for example in this example it will give both an id now say u do
var nutrition = ctx.DailyNutritionInfo.FirstOrDefault();
Product newProduct = new()
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
Name = $"Product {id}",
Weight = Random.Shared.Next(2, 10),
IsVegan = Random.Shared.Next(0, 2) == 1,
IsVegetarian = Random.Shared.Next(0, 2) == 1,
Rating = Random.Shared.Next(1, 10),
DailyNutritionInfo = nutrition
};
var nutrition = ctx.DailyNutritionInfo.FirstOrDefault();
Product newProduct = new()
{
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
Name = $"Product {id}",
Weight = Random.Shared.Next(2, 10),
IsVegan = Random.Shared.Next(0, 2) == 1,
IsVegetarian = Random.Shared.Next(0, 2) == 1,
Rating = Random.Shared.Next(1, 10),
DailyNutritionInfo = nutrition
};
this 2nd product will be using the already existent nutrition
Lamar
Lamar•3mo ago
Oh OK, then should I assign the reference to the existing nutrition
leowest
leowest•3mo ago
if u don't want to create a new item yes
Lamar
Lamar•3mo ago
No, I want it to be added to an existing dailyNutrition for the currentDay Let me try it out
leowest
leowest•3mo ago
No description
No description
leowest
leowest•3mo ago
first one is dailynutrition created so u can see 2 second one are products using referencing the 2
Lamar
Lamar•3mo ago
No description
Lamar
Lamar•3mo ago
But if I add a reference to the Product of the DailyNutrition Should I also update manualy the lists of products inside DailyNutrition?
leowest
leowest•3mo ago
No description
leowest
leowest•3mo ago
if you're doing it the opposite way yes u would be adding a product to it u dont need to do both thou if u already set either the GUID on DailyNutritionInfoId or gave it the reference on DailyNutritionInfo then u dont need to add it to the collection and if u add product to the collection then u dont need to add the references to product as I understand it i.e.: if I do
var p = new Product { DailyNutritionInfoId = Guid.Parse("395fe9c1-f0d6-4224-8720-610f8cd6f6bd") };
var p = new Product { DailyNutritionInfoId = Guid.Parse("395fe9c1-f0d6-4224-8720-610f8cd6f6bd") };
this is fine, if I do
var p = new Product { DailyNutritionInfo = reference };
var p = new Product { DailyNutritionInfo = reference };
this is also fine
var p = new Product...
n.Products.Add(p); // n is a reference to a dailynutritioninfo
var p = new Product...
n.Products.Add(p); // n is a reference to a dailynutritioninfo
also fine you dont need to do all, just one of the above
Lamar
Lamar•3mo ago
It worked Thanks a lot This was the issue, I was doing both things cue the FK constraint issue
leowest
leowest•3mo ago
if u do both they collide
Lamar
Lamar•3mo ago
That's a relief
leowest
leowest•3mo ago
if u have no further questions throw a /close to mark it as solved 😉
Lamar
Lamar•3mo ago
I don't have any questions about this right now. Will continue fighting adding Identity now 🙃 . Thanks a bunch!
leowest
leowest•3mo ago
well unhappily I won't able to help u with identity asp.net side but gl