我的模型配置如下:
public class Order
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string UserId { get; set; } = null!;
public DkUser User { get; set; } = null!;
public int ShippingStatusId { get; set; }
public ShippingStatus ShippingStatus { get; set; } = null!;
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public string? CreatedBy { get; set; }
public string? UpdatedBy { get; set; }
public ICollection<Product> Products { get; set; } = new List<Product>();
public ICollection<OrderDetail> OrderDetails {get; set;} = [];
}
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Brand { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public float Price { get; set; }
public int View { get; set; }
public int CategoryId { get; set; }
public Category? Category { get; set; }
public int DiscountId { get; set; }
public Discount Discount { get; set; } = null!;
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public string? CreatedBy { get; set; }
public string? UpdatedBy { get; set; }
public ICollection<Order> Orders { get; set; } = new List<Order>();
public ICollection<OrderDetail> OrderDetails { get; set; } = [];
public ICollection<ProductPicture> ProductPictures { get; set; } = new List<ProductPicture>();
}
public class OrderDetail
{
public int ProductId { get; set; }
public Product Product { get; set; } = new();
public int OrderId { get; set; }
public Order Order { get; set; } = new();
public int Amount { get; set; }
}
class DkdbContext(DbContextOptions<DkdbContext> options) : IdentityDbContext<DkUser>(options)
{
public DbSet<Computer> Computers { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Discount> Discounts { get; set; }
public DbSet<ShippingStatus> ShippingStatuses { get; set; }
public DbSet<ProductPicture> ProductPictures { get; set; }
public DbSet<DkUser> DkUsers { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Computer>()
.HasKey(c => c.Id);
builder.Entity<Computer>()
.Property(c => c.Id)
.HasColumnType("uuid");
builder.Entity<Category>()
.HasMany(e => e.Products)
.WithOne(e => e.Category)
.HasForeignKey(e => e.CategoryId)
.IsRequired();
builder.Entity<Product>()
.HasOne(e => e.Discount)
.WithMany(e => e.Products)
.HasForeignKey(e => e.DiscountId)
.IsRequired();
builder.Entity<Product>()
.Property(e => e.CreatedDate)
.HasDefaultValueSql("current_timestamp");
builder.Entity<Product>()
.Property(e => e.UpdatedDate)
.HasDefaultValueSql("current_timestamp");
builder.Entity<Product>()
.Property(e => e.View)
.HasDefaultValue(1);
builder.Entity<Order>()
.Property(e => e.CreatedDate)
.HasDefaultValueSql("current_timestamp");
builder.Entity<Order>()
.Property(e => e.UpdatedDate)
.HasDefaultValueSql("current_timestamp");
builder.Entity<Order>()
.Property(e => e.ShippingStatusId)
.HasDefaultValue(1);
builder.Entity<ProductPicture>()
.HasOne(e => e.Product)
.WithMany(e => e.ProductPictures)
.HasForeignKey(e => e.ProductId)
.IsRequired();
// order detail config
builder.Entity<Product>()
.HasMany(e => e.Orders)
.WithMany(e => e.Products)
.UsingEntity<OrderDetail>();
builder.Entity<OrderDetail>()
.Property(e => e.Amount)
.HasDefaultValue(1);
// end order detail config
builder.Entity<ShippingStatus>()
.HasMany(e => e.Orders)
.WithOne(e => e.ShippingStatus)
.HasForeignKey(e => e.ShippingStatusId);
builder.Entity<DkUser>()
.HasMany(e => e.Orders)
.WithOne(e => e.User)
.HasForeignKey(e => e.UserId);
}
}
字符串
我想创建一个新订单,其中包含2种产品和指定的相应金额。下面是我如何实现的:
public class OrderEnpoint
{
public static void Map(WebApplication app)
{
app.MapPost("/order", async (DkdbContext db, OrderDto orderRequest, UserManager<DkUser> userManager) =>
{
if (orderRequest == null || string.IsNullOrEmpty(orderRequest.UserId))
return Results.BadRequest();
var user = await userManager.FindByIdAsync(orderRequest.UserId);
var newOrder = new Order
{
UserId = orderRequest.UserId,
CreatedBy = user?.UserName,
UpdatedBy = user?.UserName,
};
await db.Orders.AddAsync(newOrder);
await db.SaveChangesAsync();
var _OrderDetails = orderRequest.ProductOrderList
.Select(e => new OrderDetail
{
OrderId = newOrder.Id,
ProductId = e.ProductId,
Amount = e.Amount,
}).ToList();
await db.OrderDetails.AddRangeAsync(_OrderDetails);
await db.SaveChangesAsync();
return Results.Created();
});
}
}
型
下面是我的数据传输对象类:
public class OrderDto
{
public string UserId { get; set; } = string.Empty;
public List<OrderRequest> ProductOrderList { get; set; } = [];
}
public class OrderRequest
{
[Required]
public int ProductId { get; set; }
[Required]
public int Amount { get; set; }
}
型
当我调试这段代码时,我能够看到在Orders
表中创建的订单记录,但在OrderDetails
中没有。我使用postgres作为数据库。
下面是错误的样子:
Npgsql.PostgresException(0x 80004005):在关系“订单”的列“UserId”中存在空值违反了非空约束。
错误IL:失败行包含(15,null,1,2024-01-01 14:07:25.091254+00,2024-01-01 14:07:25.091254+00,null,null)。
异常数据:
严重性:错误
SqlState:23502
MessageText:关系“Orders”的列“UserId”中的空值违反非空约束
详细信息:失败行包含(15,null,1,2024-01-01 14:07:25.091254+00,2024-01-01 14:07:25.091254+00,null,null)。
SchemaName:public
表名:订单
列名称:用户ID
File:Zhongnanjiang.jpg
生产线:2003年
例程:执行约束
我希望能够创建一个新的Order
与相关的OrderDetail
分别与金额。我正在寻找解决方案,很高兴如果有人可以帮助。谢谢。
2条答案
按热度按时间i7uaboj41#
问题将在OrderDetail中出现:
字符串
这是将导航属性初始化为一个新的Order,其ID为0,[编辑:以及UserId 0和任何其他FK,即使您显式设置FK,它也将尝试将其用作订单详细信息的FK。因此,在添加OrderDetail时,它将尝试插入新的空订单,而不是引用您首先插入的现有订单,这将导致FK冲突,因为新的空订单没有设置详细信息。]
将其更改为:
型
这同样适用于Product引用。对于实体,您应该只初始化集合导航属性,而不是单独的引用。此外,当设置具有FK和导航属性的引用时,使用其中一个,理想情况下,您应该考虑使用影子FK,只使用导航属性。还应该避免多个SaveChanges。EF可以一次性管理FK和导航属性,因此,更好的方法是让EF管理FK:
型
EF会将订单和订单详情一起插入,并自动连接FK。
sxissh062#
错误应该发生在下面的代码中,建议设置断点来检查用户的状态。
字符串
修改后的代码如下:
型