ฉันมีปัญหากับ Entity Framework ใน Asp.net ฉันต้องการรับค่ารหัสทุกครั้งที่ฉันเพิ่มวัตถุในฐานข้อมูล ฉันจะทำสิ่งนี้ได้อย่างไร
SaveChanges
เพื่อรับ ID อ่านเพิ่มเติมที่นี่
ฉันมีปัญหากับ Entity Framework ใน Asp.net ฉันต้องการรับค่ารหัสทุกครั้งที่ฉันเพิ่มวัตถุในฐานข้อมูล ฉันจะทำสิ่งนี้ได้อย่างไร
SaveChanges
เพื่อรับ ID อ่านเพิ่มเติมที่นี่
คำตอบ:
มันค่อนข้างง่าย หากคุณกำลังใช้ DB สร้างรหัส (เช่นIDENTITY
ใน MS SQL) คุณเพียงแค่ต้องเพิ่มนิติบุคคลObjectSet
และบนที่เกี่ยวข้องSaveChanges
จะถูกเติมโดยอัตโนมัติสำหรับคุณ:ObjectContext
Id
using (var context = new MyContext())
{
context.MyEntities.Add(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
เอนทิตีเฟรมเวิร์กตามค่าเริ่มต้นจะติดตามแต่ละรายการINSERT
ด้วยSELECT SCOPE_IDENTITY()
เมื่อใช้Id
s ที่สร้างขึ้นอัตโนมัติ
ฉันใช้คำตอบของ Ladislav Mrnkaเพื่อดึงรหัสสำเร็จเมื่อใช้ Entity Framework แต่ฉันกำลังโพสต์ที่นี่เพราะฉันพลาดการใช้งาน (เช่นใช้ที่ที่ไม่จำเป็น) และคิดว่าฉันจะโพสต์สิ่งที่ฉันค้นพบได้ที่นี่ - กรณีที่ผู้คนกำลังมองหา "แก้ปัญหา" ปัญหาที่ฉันมี
พิจารณาออเดอร์อ็อบเจกต์ที่มีความสัมพันธ์กับต่างประเทศกับลูกค้า เมื่อฉันเพิ่มลูกค้าใหม่และสั่งซื้อใหม่ในเวลาเดียวกันฉันทำอะไรเช่นนี้;
var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
อย่างไรก็ตามในกรณีของฉันสิ่งนี้ไม่จำเป็นเพราะฉันมีความสัมพันธ์กับกุญแจต่างประเทศระหว่างลูกค้ารหัสและคำสั่งลูกค้ารหัสลูกค้า
สิ่งที่ฉันต้องทำก็แค่นี้
var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
ตอนนี้เมื่อฉันบันทึกการเปลี่ยนแปลงรหัสที่สร้างขึ้นสำหรับลูกค้าจะถูกเพิ่มในการสั่งซื้อด้วย ฉันไม่ต้องการขั้นตอนเพิ่มเติม
ฉันรู้ว่านี่ไม่ได้ตอบคำถามเดิม แต่คิดว่ามันอาจช่วยนักพัฒนาที่ยังใหม่กับ EF จากการใช้คำตอบที่ได้รับคะแนนสูงสุดสำหรับบางสิ่งที่อาจไม่จำเป็น
นอกจากนี้ยังหมายความว่าการอัปเดตเสร็จสมบูรณ์ในการทำธุรกรรมเดียวอาจหลีกเลี่ยงข้อมูล orphin (การอัปเดตทั้งหมดเสร็จสมบูรณ์หรือไม่มีเลย)
คุณต้องโหลดเอนทิตีอีกครั้งหลังจากบันทึกการเปลี่ยนแปลง เพราะมันถูกเปลี่ยนแปลงโดยทริกเกอร์ฐานข้อมูลซึ่งไม่สามารถติดตามได้โดย EF ดังนั้นเราจำเป็นต้องโหลดเอนทิตีอีกครั้งจากฐานข้อมูล
db.Entry(MyNewObject).GetDatabaseValues();
แล้วก็
int id = myNewObject.Id;
ดู @jayantha ตอบคำถามด้านล่าง:
ฉันจะรับ Id ของเอนทิตีที่แทรกในเฟรมเวิร์กเอนทิตีเมื่อใช้ defaultValue ได้อย่างไร
การหาคำตอบ @christian ในคำถามด้านล่างอาจช่วยได้เช่นกัน:
.GetDatabaseValues();
ถ้าคุณเพิ่งบันทึกโมเดลของคุณไปยังฐานข้อมูล ID ควร repopulate ให้กับโมเดลโดยอัตโนมัติ
GetDatabaseValues()
อย่างไรหากไม่ทราบ ID ของวัตถุที่ต้องการค้นหาในฐานข้อมูล
โปรดอ้างอิงลิงค์นี้
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/
คุณต้องตั้งค่าคุณสมบัติของ StoreGeneratedPattern เป็นตัวตนแล้วลองใช้รหัสของคุณเอง
หรือคุณสามารถใช้สิ่งนี้
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
StoreGeneratedPattern
เป็นชิ้นส่วนที่ขาดหายไปสำหรับฉัน
วัตถุที่คุณกำลังบันทึกควรมีความถูกต้องId
หลังจากเผยแพร่การเปลี่ยนแปลงในฐานข้อมูล
คุณสามารถรับ ID ได้หลังจากบันทึก แต่คุณสามารถสร้าง Guid ใหม่และกำหนดก่อนบันทึกได้
ฉันเจอสถานการณ์ที่ฉันต้องการแทรกข้อมูลในฐานข้อมูล & ต้องการรหัสหลักโดยใช้กรอบงานเอนทิตี สารละลาย :
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
คำตอบทั้งหมดเหมาะสมมากสำหรับสถานการณ์ของตัวเองสิ่งที่ฉันทำแตกต่างกันคือฉันกำหนด int PK โดยตรงจากวัตถุ (TEntity) ที่ Add () กลับไปที่ตัวแปร int เช่นนี้
using (Entities entities = new Entities())
{
int employeeId = entities.Employee.Add(new Employee
{
EmployeeName = employeeComplexModel.EmployeeName,
EmployeeCreatedDate = DateTime.Now,
EmployeeUpdatedDate = DateTime.Now,
EmployeeStatus = true
}).EmployeeId;
//...use id for other work
}
ดังนั้นแทนที่จะสร้างวัตถุใหม่ทั้งหมดคุณเพียงแค่ทำสิ่งที่คุณต้องการ :)
แก้ไขสำหรับนาย @GertArnold:
Add
(ถ้าเป็นDbSet.Add
) จะไม่ได้EmployeeId
อย่างน่าอัศจรรย์กำหนดค่าให้กับ
SaveChanges
ไม่ได้โดยไม่มี เป็นไปไม่ได้ ยกเว้นว่าคุณมีกระบวนการอื่น ๆ ที่กำหนดEmployeeId
ตัวอย่างเช่นในตัวEmployee
สร้างของ หรือคุณใช้ EF core ForSqlServerUseSequenceHiLo
อยู่ อย่างไรก็ตามคุณไม่ได้ให้ภาพรวมทั้งหมด
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
สิ่งนี้จะได้ผล
Repository
เป็นอะไร และ "สิ่งนี้จะได้ผล" เป็นคำอธิบาย!
มีสองกลยุทธ์:
ใช้ฐานข้อมูลที่สร้างID
( int
หรือGUID
)
จุดด้อย:
คุณควรดำเนินการSaveChanges()
เพื่อรับID
หน่วยงานที่บันทึกไว้เพียงอย่างเดียว
ข้อดี:
สามารถใช้int
ตัวตน
ใช้ไคลเอ็นต์ที่สร้างID
- GUID เท่านั้น
ข้อดี: การลดขนาดของSaveChanges
การดำเนินการ สามารถแทรกกราฟขนาดใหญ่ของวัตถุใหม่ต่อหนึ่งการดำเนินการ
จุดด้อย:
อนุญาตเฉพาะสำหรับ GUID
เมื่อคุณใช้รหัส EF 6.x ก่อน
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
และเริ่มต้นตารางฐานข้อมูลก็จะใส่
(newsequentialid())
ภายในคุณสมบัติตารางภายใต้ส่วนหัวค่าเริ่มต้นหรือการผูกช่วยให้ ID ที่จะเติมเมื่อมันถูกแทรก
ปัญหาคือถ้าคุณสร้างตารางและเพิ่ม
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
ส่วนต่อมาฐานข้อมูลการอัพเดทในอนาคตจะไม่เพิ่มกลับ (newsequentialid ())
ในการแก้ไขวิธีที่เหมาะสมคือการลบข้อมูลการย้ายให้ลบฐานข้อมูลและย้ายอีกครั้ง ... หรือคุณสามารถเพิ่ม (newsequentialid ()) ลงในตัวออกแบบตาราง
when -column- is NULL, then NEWID()