C# 使用EF Core将SQLite外键约束添加到子集合失败
已使用EF Core将订单插入SQLite数据库。尝试向该订单添加订单详细信息,如下所示,C# 使用EF Core将SQLite外键约束添加到子集合失败,c#,entity-framework-core,ef-core-3.1,microsoft.data.sqlite,C#,Entity Framework Core,Ef Core 3.1,Microsoft.data.sqlite,已使用EF Core将订单插入SQLite数据库。尝试向该订单添加订单详细信息,如下所示,SaveChanges引发异常 SQLite错误19:“外键约束失败” 代码: 在调用SaveChanges之前,我可以看到order是从数据库中正确填充的,v11ordedtail.order是保存的订单,v11ordedtail.OrderId也是正确的 OrderDetail类如下所示 public class OrderDetail { private string _OrderDetail
SaveChanges
引发异常
SQLite错误19:“外键约束失败”
代码:
在调用SaveChanges
之前,我可以看到order
是从数据库中正确填充的,v11ordedtail.order
是保存的订单,v11ordedtail.OrderId
也是正确的
OrderDetail
类如下所示
public class OrderDetail
{
private string _OrderDetailId = Guid.NewGuid().ToString();
public string OrderDetailId
{
get { return _OrderDetailId; }
set { _OrderDetailId = value; }
}
private string _OrderId;
public string OrderId
{
get { return Order.OrderId; }
set { _OrderId = Order.OrderId; }
}
public virtual Order Order { get; set; }
private string? _JobId;
public string? JobId
{
get { return Job?.JobId; }
set { _JobId = Job?.JobId; }
}
public virtual Job? Job { get; set; } // may be null for item sales
private string _ItemCode;
public string ItemCode
{
get { return _ItemCode; }
set
{
if (value.Length > Defaults.StockCodeLength)
value = value.Substring(0, Defaults.StockCodeLength);
_ItemCode = value;
}
}
private string _ItemDescription = Defaults.Description;
public string ItemDescription
{
get { return _ItemDescription; }
set
{
if (value.Equals(_ItemDescription))
return;
if (value.Length > Defaults.DescriptionLength)
value = value.Substring(0, Defaults.DescriptionLength);
_ItemDescription = value;
}
}
public decimal UnitCost { get; set; }
private int _NrUnits = 1;
public int NrUnits
{
get { return _NrUnits; }
set
{
if (value < 1)
throw new ArgumentException($"{nameof(NrUnits)} cannot be < 1");
_NrUnits = value;
}
}
public decimal UnitPrice { get; set; }
public decimal Net => Total / (1 + Order.TaxRate / 100);
public decimal Tax => Total - Net;
public decimal Total => NrUnits * UnitPrice;
public OrderDetail(string itemCode)
{
this._ItemCode = itemCode;
}
}
在数据上下文中
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
modelBuilder.Entity<Order>()
.HasKey(e => e.OrderId);
modelBuilder.Entity<Order>()
.Property(e => e.OrderId)
.ValueGeneratedNever();
modelBuilder.Entity<Order>()
.HasOne(o => o.Customer)
.WithMany(c => c.Orders)
.HasForeignKey(o => o.CustomerId);
modelBuilder.Entity<Order>()
.HasOne(o => o.ReferralSource)
.WithMany(r => r.Orders)
.HasForeignKey(o => o.ReferralSourceId);
modelBuilder.Entity<Order>()
.HasOne(o => o.StaffMember)
.WithMany(s => s.Orders)
.HasForeignKey(o => o.StaffId);
modelBuilder.Entity<OrderDetail>()
.HasKey(e => e.OrderDetailId);
modelBuilder.Entity<OrderDetail>()
.Property(e => e.OrderDetailId)
.ValueGeneratedNever();
modelBuilder.Entity<OrderDetail>()
.HasOne(d => d.Order)
.WithMany(o => o.OrderDetails)
.HasForeignKey(d => d.OrderId);
modelBuilder.Entity<OrderDetail>()
.HasOne(o => o.Job)
.WithOne(j => j.OrderDetail)
.IsRequired(false)
.HasForeignKey<Job>(jfk => jfk.OrderDetailId);
在.NET 5.0类库中,使用
Microsoft.EntityFrameworkCore.Sqlite 5.01
Microsoft.EntityFrameworkCore.Proxies 5.01
我已经能够使用SQLite数据库编辑器输入相同的数据,因此它似乎是我的代码,而不是数据
编辑1:OrderDetails
的CREATE TABLE
语句是
CREATE TABLE [OrderDetails] (
[OrderDetailId] text NOT NULL COLLATE NOCASE
,[OrderId] text NOT NULL COLLATE NOCASE
,[JobId] text NULL COLLATE NOCASE
,[ItemCode] text NOT NULL COLLATE NOCASE
,[ItemDescription] text NOT NULL COLLATE NOCASE
,[UnitCost] numeric NOT NULL
,[NrUnits] integer NOT NULL
,[UnitPrice] numeric NOT NULL
,PRIMARY KEY ([OrderDetailId])
FOREIGN KEY ( [OrderDetailId]) REFERENCES [Jobs]( [JobId] )
FOREIGN KEY ( [OrderId]) REFERENCES [Orders]( [OrderId] )
);
我已经实施了。EF输出的失败语句为
Failed executing DbCommand (47ms) [Parameters=[@p0='6d9d6827-df81-486f-9759-d50390dda980' (Nullable = false) (Size = 36), @p1='16' (Nullable = false) (Size = 2), @p2='Description' (Nullable = false) (Size = 11), @p3=NULL, @p4='1' (DbType = String), @p5='ef5011f6-8fa0-4483-a9bd-2a2b7de73ba6' (Nullable = false) (Size = 36), @p6='25.59' (DbType = String), @p7='44.8' (DbType = String)], CommandType='Text', CommandTimeout='30']
INSERT INTO "OrderDetails" ("OrderDetailId", "ItemCode", "ItemDescription", "JobId", "NrUnits", "OrderId", "UnitCost", "UnitPrice")
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7);
我在SQLIte数据库编辑器中执行相同的命令(不带参数)
INSERT INTO "OrderDetails" ("OrderDetailId", "ItemCode", "ItemDescription", "JobId", "NrUnits", "OrderId", "UnitCost", "UnitPrice")
VALUES ('6d9d6827-df81-486f-9759-d50390dda980', '16', 'Description', NULL, '1', 'ef5011f6-8fa0-4483-a9bd-2a2b7de73ba6', '25.59', '44.8');
该行已成功输入
如何使用EF Core将此订单详细信息添加到数据库中
v11OrderDetail.Order = order;
v11OrderDetail.OrderId = order.OrderId;
order.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();
而不是那些只做:
order.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();
或者不从数据库中获取订单并执行以下操作:
v11OrderDetail.OrderId = "ef5011f6-8fa0-4483-a9bd-2a2b7de73ba6";
dbase.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();
因为你已经有订单id了
而不是那些只做:
order.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();
或者不从数据库中获取订单并执行以下操作:
v11OrderDetail.OrderId = "ef5011f6-8fa0-4483-a9bd-2a2b7de73ba6";
dbase.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();
由于您已经有订单id请将您的问题包括生成的SQL表的
CREATE TABLE
语句。还添加了在调用SaveChanges()
时由EF生成的SQL语句(请参阅)。并提供,执行时将生成相同的错误消息。作业表中是否存在OrderDetailId?订单是否存在。订单详细信息不存在。@Vague外键([OrderDetailId])引用[Jobs]([JobId])
,这是正确的外键吗?OrderDetailId
列应该是Jobs
表中的值?您不想使用OrderDetail.JobId
列作为外键吗?Yoiks!你完全正确@Progman。我一直盯着这个,直到我脸色发青。请将此作为答案发布,我将标记为正确。请将您的问题包括生成的SQL表的CREATE TABLE
语句。还添加了在调用SaveChanges()
时由EF生成的SQL语句(请参阅)。并提供,执行时将生成相同的错误消息。作业表中是否存在OrderDetailId?订单是否存在。订单详细信息不存在。@Vague外键([OrderDetailId])引用[Jobs]([JobId])
,这是正确的外键吗?OrderDetailId
列应该是Jobs
表中的值?您不想使用OrderDetail.JobId
列作为外键吗?Yoiks!你完全正确@Progman。我一直盯着这个,直到我脸色发青。请将此作为答案发布,我将标记为正确。感谢您的建议,但我已经尝试过这些选项。这件事我已经讨论了好几天了。在每种情况下,都会生成相同的sql和相同的异常。sql似乎是有效的,因为它在SQLite编辑器中成功运行。感谢您的建议,但我已经尝试了这些选项。这件事我已经讨论了好几天了。在每种情况下,都会生成相同的sql和相同的异常。sql在SQLite编辑器中成功运行时似乎有效。
v11OrderDetail.OrderId = "ef5011f6-8fa0-4483-a9bd-2a2b7de73ba6";
dbase.OrderDetails.Add(v11OrderDetail);
dbase.SaveChanges();