Multi-async ใน Entity Framework 6?


87

นี่คือรหัสของฉัน:

var banner = context.Banners.ToListAsync()
var newsGroup = context.NewsGroups.ToListAsync()
await Task.WhenAll(banner, newsGroup);

แต่เมื่อฉันเรียกใช้ฟังก์ชันจากคอนโทรลเลอร์ มันแสดงข้อผิดพลาด

การดำเนินการที่สองเริ่มต้นในบริบทนี้ก่อนที่การดำเนินการแบบอะซิงโครนัสก่อนหน้านี้จะเสร็จสมบูรณ์ ใช้ 'await' เพื่อให้แน่ใจว่าการดำเนินการแบบอะซิงโครนัสเสร็จสิ้นก่อนที่จะเรียกใช้เมธอดอื่นในบริบทนี้ ไม่รับประกันว่าสมาชิกอินสแตนซ์ใด ๆ จะปลอดภัยต่อเธรด

โปรดช่วยฉันแก้ปัญหานี้


ฉันมี 2 งาน ถ้าฉันรันแต่ละงาน มันคือความสำเร็จ แต่ถ้าฉันทำงานเหมือนรหัสของฉันด้านบน มันผิดพลาด
An Hv

คำตอบ:


119

ข้อยกเว้นอธิบายอย่างชัดเจนว่ามีการดำเนินการแบบอะซิงโครนัสเพียงครั้งเดียวต่อบริบทที่อนุญาตในแต่ละครั้ง

ดังนั้นคุณต้องไปawaitทีละครั้งตามที่ข้อความแสดงข้อผิดพลาดแนะนำ:

var banner = await context.Banners.ToListAsync();
var newsGroup = await context.NewsGroups.ToListAsync();

หรือคุณสามารถใช้หลายบริบท:

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);

35
เพียงแค่ทราบว่าหากคุณมีตัวแปร Lazy ที่ใช้บริบทในแบบสอบถามแม้ว่าจะรออยู่ก็ตามมันจะทำให้เกิดข้อผิดพลาดเดียวกันเพียงแค่ได้รับคุณสมบัติก่อนการสืบค้นก็เป็นเรื่องยากที่จะพบสิ่งนี้
Pedro.The.Kid

7
@ Pedro.The.Kid: ตามกฎทั่วไปอย่าใช้การโหลดแบบขี้เกียจกับการเข้าถึงฐานข้อมูลแบบอะซิงโครนัส การโหลดแบบ Lazy Load เป็นแบบซิงโครนัสเสมอดังนั้นจึงเป็นการดีกว่าที่จะใช้การรวมหรือการสืบค้นแยกต่างหากสำหรับข้อมูลเพิ่มเติม
Stephen Cleary

1
มีเหตุผลเฉพาะหรือไม่ว่าทำไมคุณต้องมีบริบทต่อแบบสอบถามแบบไม่ซิงค์ ฉันรู้สึกว่าสิ่งนี้กลายเป็นปัจจัย จำกัด
Zapnologica

1
@Zapnologica: มันเป็นเพียงวิธีที่ ES6 ออกแบบมา บริบทแต่ละคนสามารถจัดการแบบสอบถามหนึ่งในช่วงเวลาที่ ดังนั้นหากคุณเสร็จสิ้นหนึ่งแบบสอบถามก่อนที่คำถามถัดไปจะเริ่มขึ้นคุณจะต้องมีบริบทเดียวเท่านั้น เป็นเพียงปัญหาหากคุณต้องการทำแบบสอบถามหลายรายการในเวลาเดียวกัน
Stephen Cleary

@StephenCleary ฉันมีปัญหาในการค้นหาข้อความค้นหานั้นเนื่องจากฉันไม่มีอะไรเลยก่อนที่จะมีข้อยกเว้น มีวิธีให้เราค้นหาสิ่งที่กำลังดำเนินการอยู่หรือไม่? ขอบคุณ
Fabio Milheiro

4

หากคุณใช้คอนเทนเนอร์ IoC สำหรับการแทรกข้อมูลของผู้ให้บริการข้อมูลให้พิจารณาใช้ประเภท "ชั่วคราว" หรือ "PerWebRequest" สำหรับวงจรชีวิตของคุณ

ตัวอย่างเช่นhttps://github.com/castleproject/Windsor/blob/master/docs/lifestyles.md


3

หากคุณใช้ Unity สำหรับการฉีดขึ้นต่อกันด้วยรูปแบบที่เก็บตัวอย่างคุณจะได้รับข้อผิดพลาดต่อไปนี้โดยใช้บริบทสองบริบทขึ้นไปพร้อมกับ create / update / delete:

ไม่สามารถกำหนดความสัมพันธ์ระหว่างอ็อบเจ็กต์ทั้งสองได้เนื่องจากแนบกับอ็อบเจ็กต์ ObjectContext ที่แตกต่างกัน

สิ่งนี้สามารถแก้ไขได้โดยใช้ PerRequestLifetimeManager . ข้อมูลเพิ่มเติมที่นี่:

C # EF6 ทำการเรียก async หลายรายการในบริบทเดียวโดยใช้ Unity - Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.