I am using Entity Framework Core 6. I have 3 tables, order
, orderitem
and product
in SQL Server.
Primary key of order
table is id
, foreign keys in orderitem
are orderid
and product_id
. Everything is set up correctly, however, the query that EF Core 6 generated is not using product_id
, but keeps on using productId
as the foreign key to map to the product
table. Where is the best place to overwrite that?
Here is the error part:
FROM [ShipEngineOrderItems] AS [s0]
LEFT JOIN [Products] AS [p] ON [s0].[ProductId] = [p].[Id]
This is the full error message, the select statement above it uses the correct column name
Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (90ms) [Parameters=[@__orderId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT [s].[id], [s].[order_date], [t].[PId], [t].[ProductName], [t].[Price], [t].[id], [t].[Id0]
FROM [ShipEngineOrders] AS [s]
LEFT JOIN (
SELECT [s0].[product_id] AS [PId], [p].[WarehouseSku] AS [ProductName], [s0].[price] AS [Price], [s0].[id], [p].[Id] AS [Id0], [s0].[orderId]
FROM [ShipEngineOrderItems] AS [s0]
LEFT JOIN [Products] AS [p] ON [s0].[ProductId] = [p].[Id]
) AS [t] ON [s].[id] = [t].[orderId]
WHERE [s].[id] = @__orderId_0
ORDER BY [s].[id], [t].[id]fail: Microsoft.EntityFrameworkCore.Query[10100]
An exception occurred while iterating over the results of a query for context type 'Core.Data.ApplicationDbContext'.
Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'ProductId'.
Here is my code:
public partial class Order
{
public int id { get; set; }
public DateTime order_date { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public partial class OrderItem
{
public int id { get; set; }
[Column(TypeName = "decimal(18,2")]
public decimal price { get; set; }
public int orderId { get; set; } // navigation property
public virtual Order Order { get; set; }
[Column("product_id")]
public int product_id { get; set; } // navigation property
public virtual Product Product { get; set; }
}
public partial class Product
{
public int Id { get; set; }
public string? WarehouseSku { get; set; }
}
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext() { }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) :
base(options) { }
public virtual DbSet<Order> Order { get; set; }
public virtual DbSet<OrderItem> OrderItem { get; set; }
public virtual DbSet<Product> Product { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.ToTable("ShipEngineOrders", t => t.ExcludeFromMigrations());
//modelBuilder.Entity<OrderItem>()
// .Property(i => i.product_id).HasColumnName("product_id");
modelBuilder.Entity<OrderItem>()
.ToTable("ShipEngineOrderItems", t => t.ExcludeFromMigrations());
modelBuilder.Entity<Product>()
.ToTable("Products", t => t.ExcludeFromMigrations());
}
}
Thank you so much for your advise
CodePudding user response:
Use Fluent API for reference. Add these 2 references
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public partial class OrderItem
{
public int id { get; set; }
[Column(TypeName = "decimal(18,2")]
public decimal price { get; set; }
[ForeignKey("Order")] // add foreign key reference here
public int orderId { get; set; } // navigation property
public virtual Order Order { get; set; }
[Column("product_id")]
[ForeignKey("Product")] //This is the foreign key reference
public int product_id { get; set; } // navigation property
public virtual Product Product { get; set; }
public virtual Order Order{ get; set; }
}
In addition, try to practise convention over configuration. If your database design is using ProductId instead of product_id. The foreign key configuration is setup automatically.This applies the same to OrderId instead of orderId