มีสองคลาส:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
เมื่อกำหนดChildId
ให้Parent
ฉันควรตรวจสอบก่อนว่ามันมีอยู่ในฐานข้อมูลหรือรอให้ฐานข้อมูลเกิดข้อยกเว้นหรือไม่
ตัวอย่างเช่น (ใช้ Entity Framework Core):
หมายเหตุการตรวจสอบประเภทนี้มีอยู่ทั่วอินเทอร์เน็ตแม้ในเอกสารอย่างเป็นทางการของ Microsoft: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using- mvc / handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application # modified-the-department-controllerแต่มีการจัดการข้อยกเว้นเพิ่มเติมสำหรับSaveChanges
นอกจากนี้โปรดทราบว่าจุดประสงค์หลักของการตรวจสอบนี้คือการส่งคืนข้อความที่เป็นมิตรและสถานะ HTTP ที่เป็นที่รู้จักแก่ผู้ใช้ API และไม่ละเว้นข้อยกเว้นฐานข้อมูลอย่างสมบูรณ์ และยกเว้นสถานที่เดียวที่จะถูกโยนอยู่ภายในSaveChanges
หรือSaveChangesAsync
โทร ... ดังนั้นจะไม่มีข้อยกเว้นใด ๆ เมื่อคุณโทรหรือFindAsync
Any
ดังนั้นหากเด็กมีอยู่ แต่ถูกลบไปก่อนSaveChangesAsync
ข้อยกเว้นจะเกิดขึ้นพร้อมกัน
ฉันทำสิ่งนี้เนื่องจากข้อเท็จจริงที่ว่าการforeign key violation
จัดรูปแบบข้อยกเว้นจะยากกว่ามากในการแสดง "เด็กที่มี id {parent.ChildId} ไม่พบ"
public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
// is this code redundant?
// NOTE: its probably better to use Any isntead of FindAsync because FindAsync selects *, and Any selects 1
var child = await _db.Children.FindAsync(parent.ChildId);
if (child == null)
return NotFound($"Child with id {parent.ChildId} could not be found.");
_db.Parents.Add(parent);
await _db.SaveChangesAsync();
return parent;
}
เมื่อเทียบกับ:
public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
_db.Parents.Add(parent);
await _db.SaveChangesAsync(); // handle exception somewhere globally when child with the specified id doesn't exist...
return parent;
}
ตัวอย่างที่สองใน Postgres จะแสดง23503 foreign_key_violation
ข้อผิดพลาด: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
ข้อเสียของการจัดการข้อยกเว้นด้วยวิธีนี้ใน ORM เช่น EF คือมันจะทำงานได้เฉพาะกับแบ็กเอนด์ฐานข้อมูลเฉพาะ หากคุณต้องการเปลี่ยนไปใช้เซิร์ฟเวอร์ SQL หรืออย่างอื่นจะไม่ทำงานอีกต่อไปเพราะรหัสข้อผิดพลาดจะเปลี่ยนไป
การจัดรูปแบบข้อยกเว้นไม่ถูกต้องสำหรับผู้ใช้อาจทำให้บางสิ่งที่คุณไม่ต้องการให้ใครนอกจากนักพัฒนาเห็น
ที่เกี่ยวข้อง:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
เช่น และการจัดรูปแบบ "การละเมิดคีย์ต่างประเทศ" ฉันคิดว่าแย่ลงในกรณีนี้