ที่เก็บควรส่งคืน IQueryable หรือไม่


66

IQueryableฉันได้รับการเห็นมากของโครงการที่มีพื้นที่เก็บข้อมูลที่ส่งกลับกรณีของ สิ่งนี้อนุญาตให้ตัวกรองเพิ่มเติมและการเรียงลำดับสามารถทำได้บนIQueryableโดยรหัสอื่นซึ่งแปลเป็น SQL ที่แตกต่างกันที่ถูกสร้างขึ้น ฉันอยากรู้ว่าแบบนี้มาจากไหนและเป็นความคิดที่ดีหรือไม่

ความกังวลที่ใหญ่ที่สุดของฉันคือการที่IQueryableสัญญาว่าจะตีฐานข้อมูลในภายหลังเมื่อมีการแจกแจง นี่หมายความว่าจะเกิดข้อผิดพลาดนอกที่เก็บ นี่อาจหมายถึงข้อยกเว้น Entity Framework เกิดขึ้นในเลเยอร์อื่นของแอปพลิเคชัน

ฉันยังพบปัญหากับชุดผลลัพธ์ที่ใช้งานหลายรายการ (MARS) ในอดีต (โดยเฉพาะเมื่อใช้ธุรกรรม) และวิธีการนี้ดูเหมือนว่าจะทำให้เกิดเหตุการณ์นี้บ่อยขึ้น

ฉันได้เรียกAsEnumerableหรือToArrayตอนท้ายของแต่ละนิพจน์ LINQ ของฉันเสมอเพื่อให้แน่ใจว่ามีการเข้าใช้ฐานข้อมูลก่อนที่จะออกจากที่เก็บรหัส

ฉันสงสัยว่าการส่งคืนIQueryableอาจมีประโยชน์ในแบบ Building Block สำหรับชั้นข้อมูลหรือไม่ IQueryableฉันได้เห็นรหัสฟุ่มเฟือยสวยบางคนที่มีพื้นที่เก็บข้อมูลการเรียกเก็บข้อมูลอื่นที่จะสร้างที่ยิ่งใหญ่


จะมีความแตกต่างอะไรถ้าฐานข้อมูลไม่พร้อมใช้งานในขณะดำเนินการสอบถามเลื่อนเวลาออกไปเทียบกับช่วงเวลาของการสร้างแบบสอบถาม รหัสการบริโภคจะต้องจัดการกับสถานการณ์นั้นโดยไม่คำนึงถึง
Steven Evers

คำถามที่น่าสนใจ แต่มันอาจจะตอบยาก การค้นหาง่าย ๆ แสดงให้เห็นถึงการถกเถียงที่ค่อนข้างร้อนแรงเกี่ยวกับคำถามของคุณ: duckduckgo.com/?q=repository+return+iqueryable
Corbin มีนาคม

6
ทุกอย่างลงมาว่าคุณต้องการอนุญาตให้ลูกค้าเพิ่มส่วนคำสั่ง Linq ที่อาจได้รับประโยชน์จากการดำเนินการรอการตัดบัญชีหรือไม่ หากพวกเขาเพิ่มwhereข้อที่จะรอการตัดบัญชีIQueryableที่คุณจะต้องส่งที่ข้อมูลผ่านสายที่ไม่ได้ชุดผลลัพธ์ทั้งหมด
Robert Harvey

หากคุณใช้รูปแบบพื้นที่เก็บข้อมูล - ไม่คุณไม่ควรส่งคืน IQueryable นี่เป็นสิ่งที่ดีว่าทำไม
Arnis Lapsa

1
@SteveEvers มีความแตกต่างอย่างมาก หากมีข้อยกเว้นเกิดขึ้นในที่เก็บของฉันฉันสามารถสรุปได้ด้วยประเภทข้อยกเว้นเฉพาะเลเยอร์ข้อมูล หากเกิดขึ้นในภายหลังฉันต้องจับภาพประเภทข้อยกเว้นดั้งเดิมที่นั่น ยิ่งฉันอยู่ใกล้แหล่งที่มาของข้อยกเว้นยิ่งมีแนวโน้มที่ฉันจะรู้ว่าเกิดอะไรขึ้น นี่เป็นสิ่งสำคัญสำหรับการสร้างข้อความแสดงข้อผิดพลาดที่มีความหมาย IMHO การอนุญาตให้มีข้อยกเว้นเฉพาะของ EF ที่จะออกจากที่เก็บของฉันเป็นการละเมิด encapsulation
สวนสาธารณะเทรวิส

คำตอบ:


47

การกลับมาของ IQueryable จะทำให้ผู้บริโภคของพื้นที่เก็บข้อมูลมีความยืดหยุ่นมากขึ้น มันทำให้ความรับผิดชอบในการ จำกัด ผลลัพธ์ให้แคบลงไปถึงลูกค้าซึ่งโดยปกติจะเป็นประโยชน์และเป็นไม้ค้ำ

ในแง่ดีคุณไม่จำเป็นต้องสร้างวิธีการเก็บข้อมูลมากมาย (อย่างน้อยในเลเยอร์นี้) - GetAllActiveItems, GetAllNonActiveItems ฯลฯ - เพื่อรับข้อมูลที่คุณต้องการ อาจขึ้นอยู่กับว่าคุณพอใจหรือไม่ คุณจะต้อง (/ ควร) กำหนดสัญญาเชิงพฤติกรรมที่การติดตั้งใช้งานของคุณเป็นไปตามที่กำหนด

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

ในอีกทางหนึ่งตอนนี้คุณให้ปืนลูกซองแก่ผู้ใช้ของคุณ พวกเขาสามารถทำสิ่งต่าง ๆ ที่คุณอาจไม่ได้ตั้งใจ (ใช้มากเกินไปรวมถึง) ทำการสืบค้นจำนวนมากและทำการกรองในหน่วยความจำในการใช้งานตามลำดับ ฯลฯ ) ซึ่งโดยทั่วไปแล้วจะเป็นขั้นตอนการควบคุมการทำงานและพฤติกรรมเพราะคุณให้ การเข้าถึงแบบเต็ม

ดังนั้นขึ้นอยู่กับทีมประสบการณ์ขนาดของแอพชั้นและสถาปัตยกรรมโดยรวม ... ขึ้นอยู่กับ: - \


โปรดทราบว่าคุณสามารถทำได้หากคุณต้องการทำงานให้คืนค่า IQueryable ของคุณซึ่งจะเรียกฐานข้อมูล แต่เพิ่มการควบคุมการทำงานและพฤติกรรม
psr

1
@psr คุณสามารถอธิบายสิ่งที่คุณหมายถึงโดยสิ่งนี้?
Travis Parks

1
@ TravisParks - IQueryable ไม่จำเป็นต้องถูกปรับใช้โดย DB คุณสามารถเขียนคลาส IQueryable ได้ด้วยตัวเอง - มันค่อนข้างยาก ดังนั้นคุณสามารถเขียน wrapper IQueryable รอบ ๆ ฐานข้อมูล IQueryable และให้ IQueryable ของคุณ จำกัด การเข้าถึงฐานข้อมูลพื้นฐาน แต่นี่ยากพอที่ฉันจะไม่คาดหวังว่าจะทำได้อย่างกว้างขวาง
psr

2
โปรดทราบว่าแม้ว่าคุณจะไม่ส่งคืน IQueryables คุณยังสามารถป้องกันไม่ให้มีวิธีการมากมาย (GetAllActiveItems, GetAllNonActiveItems และอื่น ๆ ) เพียงแค่ส่งผ่านExpression<Func<Foo,bool>>วิธีการของคุณ พารามิเตอร์นี้สามารถส่งผ่านไปยังWhereเมธอดได้โดยตรงทำให้ผู้บริโภคสามารถเลือกตัวกรองโดยไม่จำเป็นต้องเข้าถึง IQueryable <Foo> โดยตรง
Flater

1
@hanzolo: ขึ้นอยู่กับสิ่งที่คุณหมายถึงด้วยการปรับโครงสร้าง มันเป็นความจริงที่การเปลี่ยนแปลงการออกแบบ (เช่นการเพิ่มสาขาใหม่หรือการเปลี่ยนความสัมพันธ์) เป็นเรื่องที่เจ็บปวดมากขึ้นเมื่อคุณมีโคเดอร์โค้ดแบบเลเยอร์และแบบคู่ที่หลวม แต่การเปลี่ยนโครงสร้างนั้นมีความเจ็บปวดน้อยกว่าเมื่อคุณต้องการเปลี่ยนเพียงหนึ่งเลเยอร์ ทุกอย่างขึ้นอยู่กับว่าคุณคาดหวังที่จะออกแบบแอปพลิเคชันใหม่หรือไม่หรือว่าคุณเพียงแค่ปรับโครงสร้างการใช้งานของคุณด้วยสถาปัตยกรรมพื้นฐานเดียวกัน ฉันจะยังคงสนับสนุนการมีเพศสัมพันธ์แบบหลวม ๆ ในกรณีใดกรณีหนึ่ง แต่คุณไม่ผิดที่จะเพิ่มการปรับโครงสร้างใหม่เมื่อเปลี่ยนแนวคิดโดเมนหลัก
Flater

29

การเปิดเผย IQueryable ไปยังส่วนต่อประสานสาธารณะไม่ใช่วิธีปฏิบัติที่ดี เหตุผลเป็นพื้นฐาน: คุณไม่สามารถให้การรับรู้ด้วย IQueryable ตามที่กล่าวไว้

ส่วนต่อประสานสาธารณะเป็นสัญญาระหว่างผู้ให้บริการและลูกค้า และในกรณีส่วนใหญ่มีความคาดหวังของการใช้งานเต็มรูปแบบ IQueryable เป็นการโกง:

  1. IQueryable แทบเป็นไปไม่ได้ที่จะนำไปใช้ และในปัจจุบันยังไม่มีวิธีแก้ไขที่เหมาะสม แม้ Entity Framework มีจำนวนมากUnsupportedExceptions
  2. วันนี้ผู้ให้บริการที่สืบค้นได้มีการพึ่งพาโครงสร้างพื้นฐานขนาดใหญ่ Sharepoint มีการนำไปใช้บางส่วนและผู้ให้บริการ SQL ของฉันมีการนำไปใช้บางส่วนอย่างชัดเจน

รูปแบบพื้นที่เก็บข้อมูลช่วยให้เราเห็นภาพชัดเจนโดยการฝังรากลึกและที่สำคัญที่สุดคือความเป็นอิสระของการทำให้เกิดผล ดังนั้นเราสามารถเปลี่ยนแหล่งข้อมูลในอนาคต

คำถามคือ " ควรมีความเป็นไปได้ของการทดแทนแหล่งข้อมูลหรือไม่ "

ถ้าพรุ่งนี้สามารถย้ายข้อมูลส่วนหนึ่งไปยังบริการ SAP ฐานข้อมูล NoSQL หรือเพียงแค่ไฟล์ข้อความเราสามารถรับประกันได้ว่าการใช้งานอินเตอร์เฟซ IQueryable เหมาะสมหรือไม่

( คะแนนที่ดีขึ้นเกี่ยวกับสาเหตุที่การปฏิบัตินี้ไม่ดี)


คำตอบนี้ไม่สามารถยืนได้ด้วยตนเองโดยไม่ปรึกษาลิงก์ภายนอกที่ระเหยได้ พิจารณาสรุปประเด็นสำคัญที่ทำโดยทรัพยากรภายนอกอย่างน้อยและพยายามแยกความเห็นส่วนตัวออกจากคำตอบของคุณ ("ความคิดที่เลวร้ายที่สุดที่ฉันเคยได้ยิน") นอกจากนี้ให้ลองลบข้อมูลโค้ดที่ดูเหมือนไม่เกี่ยวข้องกับ IQueryable
Lars Viklund

1
ขอบคุณ @LarsViklund คำตอบจะได้รับการอัปเดตด้วยตัวอย่างและคำอธิบายปัญหา
Artru

19

ในความเป็นจริงคุณมีสามทางเลือกถ้าคุณต้องการการดำเนินการที่เลื่อนออกไป:

  • มันทำวิธีนี้ - IQueryableเปิดเผย
  • ใช้โครงสร้างที่แสดงวิธีการเฉพาะสำหรับตัวกรองเฉพาะหรือ "คำถาม" ( GetCustomersInAlaskaWithChildrenด้านล่าง)
  • ใช้โครงสร้างที่เปิดเผยตัวกรอง / เรียงลำดับ / หน้า API อย่างยิ่งและสร้างIQueryableภายใน

ฉันชอบอันที่สาม (แต่ฉันได้ช่วยเพื่อนร่วมงานนำไปใช้ในครั้งที่สองด้วย) แต่มีบางอย่างที่เกี่ยวข้องกับการตั้งค่าและการบำรุงรักษา (T4 เพื่อช่วยเหลือ!)

แก้ไข : หากต้องการกำจัดความสับสนรอบ ๆ สิ่งที่ฉันกำลังพูดถึงให้พิจารณาตัวอย่างต่อไปนี้ที่ถูกขโมยจากIQueryable สามารถฆ่าสุนัขของคุณขโมยภรรยาของคุณฆ่าความตั้งใจของคุณเพื่อมีชีวิต ฯลฯ

ในสถานการณ์ที่คุณจะเปิดเผยสิ่งนี้:

public class CustomerRepo : IRepo 
{ 
     private DataContext ct; 
     public Customer GetCustomerById(int id) { ... } 
     public Customer[] GetCustomersInAlaskaWithChildren() { ... } 
} 

API ที่ฉันกำลังพูดถึงจะช่วยให้คุณเปิดเผยวิธีการที่จะช่วยให้คุณแสดงGetCustomersInAlaskaWithChildren(หรือชุดค่าผสมอื่น ๆ ) อย่างยืดหยุ่นและ repo จะเรียกใช้เป็น IQueryable และส่งคืนผลลัพธ์ให้คุณ แต่สิ่งสำคัญคือมันทำงานภายในเลเยอร์ที่เก็บดังนั้นจึงยังคงใช้ประโยชน์จากการดำเนินการรอการตัดบัญชี เมื่อคุณได้ผลลัพธ์กลับมาคุณยังคงสามารถ LINQ-to-objects บนเนื้อหาในหัวใจของคุณ

ข้อดีอีกประการของวิธีการเช่นนี้ก็คือเนื่องจากเป็นคลาส POCO ที่เก็บนี้สามารถใช้งานได้หลังเว็บหรือบริการ WCF สามารถสัมผัสกับ AJAX หรือผู้โทรอื่น ๆ ที่ไม่รู้จักสิ่งแรกเกี่ยวกับ LINQ


4
ดังนั้นคุณจะต้องสร้าง API การสืบค้นเพื่อแทนที่ API การสืบค้นในตัวของ NET หรือไม่
Michael Brown

4
ฟังดูไม่มีประโยชน์กับฉันเลย
ozz

7
@MikeBrown จุดของคำถามนี้ - และคำตอบของฉัน - คือการที่คุณต้องการที่จะเผยให้เห็นพฤติกรรมหรือข้อได้เปรียบของการIQueryable ได้โดยไม่ต้องเปิดเผยIQueryableตัวเอง คุณจะทำอย่างไรกับ API ในตัว
GalacticCowboy

2
นั่นเป็นคำพูดที่ดีมาก คุณยังไม่ได้อธิบายว่าทำไมคุณต้องการหลีกเลี่ยงสิ่งนั้น Heck WCF Data Services เปิดเผย IQueryable ทั่วทั้งสาย ฉันไม่ได้พยายามที่จะเลือกคุณฉันแค่ไม่เข้าใจความเกลียดชังต่อคน IQueryable คนนี้ดูเหมือนจะมี
Michael Brown

2
หากคุณต้องการใช้ IQueryable ดังนั้นทำไมคุณถึงต้องใช้พื้นที่เก็บข้อมูล? ที่เก็บมีวัตถุประสงค์เพื่อซ่อนรายละเอียดการใช้งาน (นอกจากนี้ WCF Data Services ค่อนข้างใหม่กว่าโซลูชันส่วนใหญ่ที่ฉันเคยทำในช่วง 4 ปีที่ผ่านมาซึ่งใช้ที่เก็บข้อมูลเช่นนี้ ... ดังนั้นจึงไม่น่าที่พวกเขาจะได้รับการอัปเดตทุกเวลาในไม่ช้า ใช้ของเล่นใหม่ที่เป็นประกาย)
GalacticCowboy

8

มีคำตอบที่ถูกต้องเพียงข้อเดียวเท่านั้นจริง ๆ ขึ้นอยู่กับว่าจะใช้พื้นที่เก็บข้อมูลอย่างไร

ที่เก็บของคุณสุดขีดจะมีเสื้อคลุมบาง ๆ รอบ ๆ DBContext เพื่อให้คุณสามารถอัดวีเนียร์ของความสามารถในการทดสอบรอบ ๆ แอพที่ขับเคลื่อนด้วยฐานข้อมูล ไม่มีความคาดหวังในโลกแห่งความเป็นจริงที่ว่าสิ่งนี้อาจถูกนำมาใช้ในลักษณะที่ไม่ได้เชื่อมต่อโดยไม่มีฐานข้อมูลที่เป็นมิตรกับ LINQ เพราะแอพ CRUD ของคุณไม่ต้องการ ถ้างั้นทำไมไม่ใช้ IQueryable ล่ะ? ฉันอาจต้องการ IEnumarable เพราะคุณได้รับประโยชน์มากที่สุด [อ่าน: การดำเนินการล่าช้า] และไม่รู้สึกสกปรก

ฉันจะพยายามอย่างหนักเพื่อใช้ประโยชน์จากรูปแบบของพื้นที่เก็บข้อมูลและส่งคืนคอลเลกชันที่เป็นรูปธรรมที่เหมาะสมซึ่งไม่มีความหมายของการเชื่อมต่อฐานข้อมูลพื้นฐาน


6
เกี่ยวกับการกลับมาIEnumerableเป็นสิ่งสำคัญที่จะต้องทราบว่า((IEnumerable<T>)query).LastOrDefault()แตกต่างกันมากquery.LastOrDefault()( queryถือว่าเป็นIQueryable) ดังนั้นมันกลับสมเหตุสมผลIEnumerableถ้าคุณจะทำซ้ำผ่านองค์ประกอบทั้งหมดต่อไป
Lou

7
 > Should Repositories return IQueryable?

ไม่ถ้าคุณต้องการทำการทดสอบพัฒนา / unittesting เพราะไม่มีวิธีง่าย ๆ ในการสร้างที่เก็บจำลองเพื่อทดสอบ businesslogic ของคุณ (= พื้นที่เก็บข้อมูลผู้บริโภค) แยกจากฐานข้อมูลหรือผู้ให้บริการ IQueryable อื่น ๆ


6

จากมุมมองของสถาปัตยกรรมที่บริสุทธิ์ IQueryable เป็นสิ่งที่เป็นนามธรรม โดยทั่วไปแล้วจะให้พลังงานแก่ผู้ใช้มากเกินไป ที่ถูกกล่าวว่ามีสถานที่ที่เหมาะสม ถ้าคุณใช้ OData, IQueryable ทำให้เป็นเรื่องง่ายมากที่จะให้จุดปลายที่กรองได้ง่ายเรียงลำดับจัดกลุ่ม ... ฯลฯ ฉันชอบสร้าง DTO ที่หน่วยงานของฉันทำแผนที่และ IQueryable จะคืนค่า DTO แทน ด้วยวิธีนี้ฉันกรองข้อมูลล่วงหน้าของฉันและใช้วิธีการ IQueryable เท่านั้นเพื่อให้ลูกค้าสามารถปรับแต่งผลลัพธ์ได้


6

ฉันต้องเผชิญกับทางเลือกเช่นนี้เช่นกัน

ดังนั้นขอสรุปด้านบวกและลบ:

บวก:

  • มีความยืดหยุ่น แน่นอนว่ามีความยืดหยุ่นและสะดวกในการอนุญาตให้ฝั่งไคลเอ็นต์สร้างเคียวรีที่กำหนดเองด้วยวิธีการเก็บข้อมูลเดียว

เชิงลบ:

  • ไม่สามารถทดสอบได้ (คุณจะทำการทดสอบการใช้งาน IQueryable พื้นฐานซึ่งโดยปกติแล้วจะเป็น ORM ของคุณ แต่คุณควรทดสอบตรรกะของคุณแทน)
  • พร่าเลือนความรับผิดชอบ เป็นไปไม่ได้ที่จะบอกว่าวิธีการเก็บข้อมูลของคุณนั้นทำอะไร จริงๆแล้วมันเป็นวิธีการของพระเจ้าที่สามารถคืนสิ่งที่คุณต้องการในฐานข้อมูลทั้งหมดของคุณ
  • ไม่ปลอดภัย โดยไม่มีข้อ จำกัด เกี่ยวกับสิ่งที่สามารถสอบถามได้โดยวิธีการเก็บข้อมูลนี้ในบางกรณีการใช้งานดังกล่าวอาจไม่ปลอดภัยจากจุดรักษาความปลอดภัย
  • ปัญหาการแคช (หรือเป็นปัญหาทั่วไปก่อนหรือหลังการประมวลผล) โดยทั่วไปแล้วมันไม่ฉลาดที่จะแคชทุกสิ่งในแอปพลิเคชันของคุณ คุณจะพยายามแคชสิ่งที่ทำให้ฐานข้อมูลของคุณโหลดอย่างมีนัยสำคัญ แต่วิธีการทำนั้นถ้าคุณมีวิธีการเก็บข้อมูลเพียงวิธีเดียวที่ลูกค้าใช้ในการออกแบบสอบถามใด ๆ กับฐานข้อมูลจริงหรือไม่
  • ปัญหาการเข้าสู่ระบบ การบันทึกสิ่งที่เลเยอร์ที่เก็บจะทำให้คุณตรวจสอบ IQueryable ก่อนเพื่อตรวจสอบว่าการโทรนี้ถูกบันทึกหรือไม่

ฉันจะแนะนำไม่ให้ใช้วิธีนี้ พิจารณาสร้างข้อมูลจำเพาะหลาย ๆ แบบและใช้วิธีการเก็บข้อมูลแทนซึ่งสามารถสืบค้นฐานข้อมูลโดยใช้วิธีเหล่านั้นได้ รูปแบบข้อมูลจำเพาะเป็นวิธีที่ยอดเยี่ยมในการสรุปชุดเงื่อนไข


5

ฉันคิดว่าการเปิดเผย IQueryable บนพื้นที่เก็บข้อมูลของคุณนั้นเป็นที่ยอมรับได้อย่างสมบูรณ์ในช่วงเริ่มต้นของการพัฒนา มีเครื่องมือ UI ที่สามารถทำงานกับ IQueryable ได้โดยตรงและจัดการการเรียงลำดับการกรองการจัดกลุ่ม ฯลฯ

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

สำหรับการทำซ้ำสองสามครั้งแรกของโครงการการเปิดเผย IQueryable ต่อสาธารณะบนพื้นที่เก็บข้อมูลช่วยให้การเติบโตเร็วขึ้น ก่อนที่จะวางจำหน่ายครั้งแรกฉันขอแนะนำให้ตั้งค่าการดำเนินการแบบสอบถามให้เป็นแบบส่วนตัวหรือป้องกัน


4

สิ่งที่ฉันได้เห็น (และสิ่งที่ฉันนำไปปฏิบัติ) คือ:

public interface IEntity<TKey>
{
    TKey Id { get; set; }
}

public interface IRepository<TEntity, in TKey> where TEntity : IEntity<TKey>
{
    void Create(TEntity entity);
    TEntity Get(TKey key);
    IEnumerable<TEntity> GetAll();
    IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression);
    void Update(TEntity entity);
    void Delete(TKey id);
}

สิ่งนี้ช่วยให้คุณทำคือการมีความยืดหยุ่นในการทำIQueryable.Where(a => a.SomeFilter)แบบสอบถามใน repo ของคุณโดยconcreteRepo.GetAll(a => a.SomeFilter)ไม่ต้องเปิดเผยธุรกิจ LINQy

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.