更新记录时出现 SQLite 错误 19: 'UNIQUE constraint failed' with Entity Framework Core
Getting a SQLite Error 19: 'UNIQUE constraint failed' with Entity Framework Core when updating a record
我有一个发票对象,其中有一个客户对象 属性。当我尝试更新我的发票对象时,我收到此 SQLite 错误 19: 'UNIQUE constraint failed: Client.InvoiceId'。我尝试按照另一篇关于同一问题的文章的建议进行操作,即在调用 SaveChanges() 之前添加一条 Attach 语句,但这没有用:
_context.Invoices.Attach(invoice);
这是我的数据模型:
public class Invoice
{
public string InvoiceId { get; set; } = GenerateID.GenerateInvoiceID();
public string Description { get; set; }
public List<InvoiceItem> Items { get; set; }
public DateTime InvoiceDate { get; set; }
public string PaymentTerms { get; set; }
public DateTime PaymentDue { get; set; }
public int TotalPrice { get; set; }
public string Status { get; set; } = "pending";
public Client Client { get; set; }
public string BillFromAddress { get; set; }
public string BillFromCity { get; set; }
public string BillFromCountry { get; set; }
public string BillFromPostal { get; set; }
}
public class Client
{
public string ClientId{ get; set; } = GenerateID.GenerateClientID();
public string InvoiceId { get; set; }
[Required]
public string ClientName { get; set; }
[Required]
public string ClientEmail { get; set; }
[Required]
public string ClientAddress { get; set; }
[Required]
public string ClientCity { get; set; }
[Required]
public string ClientCountry { get; set; }
[Required]
public string ClientPostal { get; set; }
}
public class InvoiceItem
{
public string InvoiceItemId { get; set; } = GenerateID.GenerateItemID();
public string InvoiceId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public int Price { get; set; }
public InvoiceItem()
{
}
public InvoiceItem(string itemName, int quantity, int price)
{
Name = itemName;
Quantity = quantity;
Price = price;
}
}
这是更新发票的服务:
public async void EditInvoice(InputModel input, string id)
{
var invoice = await _context.Invoices.FindAsync(id);
if (invoice == null) { throw new Exception("Unable to find the invoice"); }
invoice.Items = input.Items;
invoice.Description = input.Description;
invoice.InvoiceDate = input.InvoiceDate;
invoice.PaymentTerms = input.PaymentTerms;
invoice.Client = input.Client;
invoice.BillFromAddress = input.BillFromAddress;
invoice.BillFromCity = input.BillFromCity;
invoice.BillFromCountry = input.BillFromCountry;
invoice.BillFromPostal = input.BillFromPostal;
await _context.SaveChangesAsync();
}
这是我的 InputModel class:
public class InputModel
{
[Required]
public string Description { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime InvoiceDate { get; set; }
public string PaymentTerms { get; set; }
public DateTime PaymentDue { get; set; }
public Client Client { get; set; }
public List<InvoiceItem> Items { get; set; } = new List<InvoiceItem>(16);
[Required]
public string BillFromAddress { get; set; }
[Required]
public string BillFromCity { get; set; }
[Required]
public string BillFromCountry { get; set; }
[Required]
public string BillFromPostal { get; set; }
public void PopulateItems()
{
for (int i = 0; i < Items.Capacity; i++)
{
Items.Add(new InvoiceItem());
}
}
}
这是我的 CreateInvoice PageModel
public class CreateInvoiceModel : PageModel
{
public readonly InvoiceService _service;
[BindProperty]
public InputModel Input { get; set; }
public CreateInvoiceModel(InvoiceService service)
{
_service = service;
}
public void OnGet()
{
Input = new InputModel();
Input.PopulateItems();
}
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
_service.AddInvoice(Input);
return RedirectToPage("/Index");
}
return Page();
}
}
这是我的 EditInvoice PageModel
public class EditInvoiceModel : PageModel
{
public readonly InvoiceService _service;
[BindProperty]
public InputModel Input { get; set; }
public string InvoiceId { get; set; }
public EditInvoiceModel(InvoiceService service)
{
_service = service;
}
public async void OnGet(string id)
{
Invoice invoice = await _service.GetInvoice(id);
InvoiceId = invoice.InvoiceId;
Input = new InputModel();
Input.Items = invoice.Items;
Input.BillFromAddress = invoice.BillFromAddress;
Input.BillFromCity = invoice.BillFromCity;
Input.BillFromPostal = invoice.BillFromPostal;
Input.BillFromCountry = invoice.BillFromCountry;
Input.Client = invoice.Client;
Input.InvoiceDate = invoice.InvoiceDate;
Input.PaymentTerms = invoice.PaymentTerms;
Input.Description = invoice.Description;
}
public async Task<IActionResult> OnPost(string id)
{
if(ModelState.IsValid)
{
_service.EditInvoice(Input, id);
return RedirectToPage("/ViewInvoice", new { id = id });
}
return Page();
}
}
这是我的 DbContext class:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Invoice> Invoices { get; set; }
}
我假设正在发生的事情是 ChangeTracker 跟踪您在 EditInvoice 方法中设置为新实体的客户端,并尝试将其插入数据库。但是因为您将 Client 和 Invoice 映射为 1 对 1 关系,所以插入失败。
因此,由于一个客户真的可以拥有多张发票,因此您需要进行以下更改:
客户端
删除 InvoiceId
public class Client
{
public string ClientId { get; set; } = GenerateID.GenerateClientID();
// public string InvoiceId { get; set; }
/* omitted for brevity */
}
真的删除这一行。我只是将其注释掉以使其清楚。
发票
添加 ClientId
public class Invoice
{
public string InvoiceId { get; set; } = GenerateID.GenerateInvoiceID();
public string ClientId { get; set; }
/* omitted for brevity */
}
输入模型
将 Client
对象更改为 ClientId
public class InputModel
{
// public Client Client { get; set; }
public string ClientId { get; set; }
/* omitted for brevity */
}
EditInvoice 方法
更新 ClientId 而不是整个 Client 对象
invoice.ClientId = input.ClientId;
您可以在 EntityFrameworkCore 中阅读更多关于关系的信息 here。
如果这对你有用,请告诉我。
我有一个发票对象,其中有一个客户对象 属性。当我尝试更新我的发票对象时,我收到此 SQLite 错误 19: 'UNIQUE constraint failed: Client.InvoiceId'。我尝试按照另一篇关于同一问题的文章的建议进行操作,即在调用 SaveChanges() 之前添加一条 Attach 语句,但这没有用:
_context.Invoices.Attach(invoice);
这是我的数据模型:
public class Invoice
{
public string InvoiceId { get; set; } = GenerateID.GenerateInvoiceID();
public string Description { get; set; }
public List<InvoiceItem> Items { get; set; }
public DateTime InvoiceDate { get; set; }
public string PaymentTerms { get; set; }
public DateTime PaymentDue { get; set; }
public int TotalPrice { get; set; }
public string Status { get; set; } = "pending";
public Client Client { get; set; }
public string BillFromAddress { get; set; }
public string BillFromCity { get; set; }
public string BillFromCountry { get; set; }
public string BillFromPostal { get; set; }
}
public class Client
{
public string ClientId{ get; set; } = GenerateID.GenerateClientID();
public string InvoiceId { get; set; }
[Required]
public string ClientName { get; set; }
[Required]
public string ClientEmail { get; set; }
[Required]
public string ClientAddress { get; set; }
[Required]
public string ClientCity { get; set; }
[Required]
public string ClientCountry { get; set; }
[Required]
public string ClientPostal { get; set; }
}
public class InvoiceItem
{
public string InvoiceItemId { get; set; } = GenerateID.GenerateItemID();
public string InvoiceId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public int Price { get; set; }
public InvoiceItem()
{
}
public InvoiceItem(string itemName, int quantity, int price)
{
Name = itemName;
Quantity = quantity;
Price = price;
}
}
这是更新发票的服务:
public async void EditInvoice(InputModel input, string id)
{
var invoice = await _context.Invoices.FindAsync(id);
if (invoice == null) { throw new Exception("Unable to find the invoice"); }
invoice.Items = input.Items;
invoice.Description = input.Description;
invoice.InvoiceDate = input.InvoiceDate;
invoice.PaymentTerms = input.PaymentTerms;
invoice.Client = input.Client;
invoice.BillFromAddress = input.BillFromAddress;
invoice.BillFromCity = input.BillFromCity;
invoice.BillFromCountry = input.BillFromCountry;
invoice.BillFromPostal = input.BillFromPostal;
await _context.SaveChangesAsync();
}
这是我的 InputModel class:
public class InputModel
{
[Required]
public string Description { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime InvoiceDate { get; set; }
public string PaymentTerms { get; set; }
public DateTime PaymentDue { get; set; }
public Client Client { get; set; }
public List<InvoiceItem> Items { get; set; } = new List<InvoiceItem>(16);
[Required]
public string BillFromAddress { get; set; }
[Required]
public string BillFromCity { get; set; }
[Required]
public string BillFromCountry { get; set; }
[Required]
public string BillFromPostal { get; set; }
public void PopulateItems()
{
for (int i = 0; i < Items.Capacity; i++)
{
Items.Add(new InvoiceItem());
}
}
}
这是我的 CreateInvoice PageModel
public class CreateInvoiceModel : PageModel
{
public readonly InvoiceService _service;
[BindProperty]
public InputModel Input { get; set; }
public CreateInvoiceModel(InvoiceService service)
{
_service = service;
}
public void OnGet()
{
Input = new InputModel();
Input.PopulateItems();
}
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
_service.AddInvoice(Input);
return RedirectToPage("/Index");
}
return Page();
}
}
这是我的 EditInvoice PageModel
public class EditInvoiceModel : PageModel
{
public readonly InvoiceService _service;
[BindProperty]
public InputModel Input { get; set; }
public string InvoiceId { get; set; }
public EditInvoiceModel(InvoiceService service)
{
_service = service;
}
public async void OnGet(string id)
{
Invoice invoice = await _service.GetInvoice(id);
InvoiceId = invoice.InvoiceId;
Input = new InputModel();
Input.Items = invoice.Items;
Input.BillFromAddress = invoice.BillFromAddress;
Input.BillFromCity = invoice.BillFromCity;
Input.BillFromPostal = invoice.BillFromPostal;
Input.BillFromCountry = invoice.BillFromCountry;
Input.Client = invoice.Client;
Input.InvoiceDate = invoice.InvoiceDate;
Input.PaymentTerms = invoice.PaymentTerms;
Input.Description = invoice.Description;
}
public async Task<IActionResult> OnPost(string id)
{
if(ModelState.IsValid)
{
_service.EditInvoice(Input, id);
return RedirectToPage("/ViewInvoice", new { id = id });
}
return Page();
}
}
这是我的 DbContext class:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Invoice> Invoices { get; set; }
}
我假设正在发生的事情是 ChangeTracker 跟踪您在 EditInvoice 方法中设置为新实体的客户端,并尝试将其插入数据库。但是因为您将 Client 和 Invoice 映射为 1 对 1 关系,所以插入失败。
因此,由于一个客户真的可以拥有多张发票,因此您需要进行以下更改:
客户端
删除 InvoiceId
public class Client
{
public string ClientId { get; set; } = GenerateID.GenerateClientID();
// public string InvoiceId { get; set; }
/* omitted for brevity */
}
真的删除这一行。我只是将其注释掉以使其清楚。
发票
添加 ClientId
public class Invoice
{
public string InvoiceId { get; set; } = GenerateID.GenerateInvoiceID();
public string ClientId { get; set; }
/* omitted for brevity */
}
输入模型
将 Client
对象更改为 ClientId
public class InputModel
{
// public Client Client { get; set; }
public string ClientId { get; set; }
/* omitted for brevity */
}
EditInvoice 方法
更新 ClientId 而不是整个 Client 对象
invoice.ClientId = input.ClientId;
您可以在 EntityFrameworkCore 中阅读更多关于关系的信息 here。
如果这对你有用,请告诉我。