เลือกเปอร์เซ็นต์ของเรกคอร์ดโดยใช้ CRM 2011 Dynamic Entity

ฉันกำลังพัฒนาบริการที่ใช้ข้อมูล CRM 2011 ผ่านเอนทิตีแบบไดนามิก (เช่นใน Microsoft.Xrm.Sdk.Entity ซึ่งเป็นวิธีการผูกล่าช้า) ฉันจงใจไม่ใช้วิธี Xrm.cs (การเชื่อมโยงตั้งแต่เนิ่นๆ) เพื่อพยายามทำให้โซลูชันของฉันเป็นแบบทั่วไป

นอกจากนี้ ฉันต้องการหลีกเลี่ยงการเชื่อมต่อกับฐานข้อมูล CRM โดยตรง (เช่น EDMX) เนื่องจากจะทำให้โซลูชันของฉันไม่สามารถใช้งานได้กับ CRM ที่โฮสต์ไว้ (เช่น ไม่มีการเข้าถึง DB โดยตรง)

ฉันมีข้อกำหนด (แบบง่าย) ต่อไปนี้ ฉันกำลังดิ้นรนกับเกณฑ์การคัดเลือก:

สุ่ม 7% ของบันทึก จำเป็นต้องเลือก (และอัปเดต)

ใน SQL เกณฑ์การคัดเลือกจะค่อนข้างง่าย - ฉันรู้วิธีเลือกเปอร์เซ็นต์ของระเบียนแบบสุ่ม สิ่งที่ต้องการ:

SELECT TOP 7 PERCENT * FROM
(
    SELECT TOP 1000 NEWID() AS Foo, [someColumns]
    FROM [someTable]
)
AS Bar ORDER BY Bar.Foo ASC

มันทำงานได้อย่างสมบูรณ์แบบ ฉันรวบรวม LINQ ที่เทียบเท่ากันเป็นดังนี้:

from e in someEntities
orderby Guid.NewGuid()
select e;

มีปัญหาเกิดขึ้น ฉันไม่รู้วิธีใช้ LINQ กับเอนทิตีไดนามิก CRM 2011 แต่กลับยืนยันที่จะใช้คลาส/ไวยากรณ์ QueryExpression ที่จำกัดหรือ fetchXML ดังที่เห็นใน หน้านี้ (MSDN)

ฉันได้ระบุตัวเลือกต่อไปนี้เพื่อให้เป็นไปตามข้อกำหนดนี้:

  1. ใช้เอนทิตีแบบไดนามิก ส่งกลับบันทึกทั้งหมดที่ตั้งไว้ในรายการ จากนั้นเลือกการเลือกแบบสุ่มตามดัชนี อย่างไรก็ตาม สิ่งนี้เกี่ยวข้องกับการส่งคืนบันทึกมากถึง 10,000 รายการผ่านบริการข้อมูลอินเทอร์เน็ต ซึ่งอาจช้า/ไม่ปลอดภัย/อื่นๆ

  2. ใช้คำสั่ง fetchXML น่าเสียดายที่ฉันไม่รู้จัก fetchXML ดังนั้นฉันจึงไม่รู้ว่าสามารถทำสิ่งต่างๆ เช่น COUNT, TOP, PERCENT หรือ NEWID() ได้หรือไม่

  3. ใช้ Xrm.cs และ LINQ หรือใช้ Stored Procedure หรือมุมมอง SQL ตัวเลือกทั้งหมดเหล่านี้หมายถึงการเชื่อมโยงโซลูชันเข้ากับการเชื่อมต่อฐานข้อมูลโดยตรงและ/หรือการเชื่อมโยงตั้งแต่เนิ่นๆ ซึ่งไม่เป็นที่ต้องการ

  4. ปฏิเสธลูกค้า

คำแนะนำใด ๆ ที่จะได้รับการชื่นชมอย่างมาก! fetchXML สามารถทำการสืบค้นนี้ได้หรือไม่ มีวิธีที่ดีกว่าในการทำเช่นนี้หรือไม่?


person Alec    schedule 15.09.2011    source แหล่งที่มา


คำตอบ (2)


FetchXML ไม่รองรับสิ่งนี้ ดังนั้นคุณจึงเหลือเพียง 1 หรือ 3 และคุณพูดถูก 3 จะใช้งานได้ในเวอร์ชัน On Premise เท่านั้น เนื่องจากคุณไม่สามารถเชื่อมต่อกับ SQL โดยตรงด้วยผลิตภัณฑ์ CRM Online ได้ อย่างไรก็ตาม นั่นคือสิ่งที่ฉันจะเลือก เว้นแต่คุณจะแน่ใจอย่างแน่นอนว่าลูกค้าจะเปลี่ยนไปใช้ CRM Online หากคุณต้องใช้ 1 อย่างน้อยคุณก็สามารถจำกัดคอลัมน์ที่ส่งคืนให้เป็นเพียง GUID ของเรกคอร์ดเพื่อลดขนาดเพย์โหลด จากนั้นเมื่อคุณเลือกบันทึกแบบสุ่ม เพียงไปรับคอลัมน์เพิ่มเติมหากจำเป็น (แน่นอนว่าสิ่งนี้อาจจบลงช้าลงเนื่องจาก "ความช่างพูด" ขึ้นอยู่กับจำนวนบันทึกสุ่มที่คุณกำลังติดต่อด้วย)

person Josh Painter    schedule 15.09.2011
comment
ฉันคิดว่าผู้กำหนดความต้องการยืนกรานว่าโซลูชันนี้สามารถใช้ได้กับสภาพแวดล้อมที่โฮสต์ ดังนั้นฉันจะส่งคืนรายการรหัสและสุ่มสิ่งเหล่านั้น ฉันโหวตแล้ว จะทำเครื่องหมายเป็นคำตอบหากวิธีนี้พิสูจน์ได้ว่าประสบความสำเร็จ ขอบคุณ :) - person Alec; 16.09.2011
comment
ฉันสามารถทำงานนี้ได้โดยใช้วิธีการที่อธิบายไว้ข้างต้น ส่งคืนชุดเต็มเป็นรายการรหัสเท่านั้น จากนั้นเลือกข้อมูลทั้งหมดหลังจากสุ่มเลือกในหน่วยความจำ ดังนั้นฉันจะใส่สิ่งนี้เป็นคำตอบเพราะมันใช้งานได้ แต่ฉันขอแนะนำให้ทุกคนที่มีข้อกำหนดที่คล้ายกันควรอ่านข้อมูลในคำตอบของ jamnap เช่นกัน ฉันยังไม่รู้ว่าโซลูชันใดมีประสิทธิภาพมากกว่า - person Alec; 19.09.2011

ณ จุดนี้ Dynamics CRM 2011 ไม่สามารถให้ระดับความสามารถในการสืบค้นที่ SQL และผู้ให้บริการ LINQ อื่นๆ สามารถให้ได้ ดังนั้นฉันเชื่อจริงๆ ว่าคุณจะต้อง ปฏิเสธลูกค้า และ ย้าย เป็นเวอร์ชันภายในองค์กรหากเขา/เธอต้องการความยืดหยุ่นแบบนั้น

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

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

สำหรับ #3 นั้น Native SQL เป็นทางออกที่ดีที่สุดของคุณในการรับทุกสิ่งที่คุณต้องการจากข้อมูลของคุณ ณ จุดนี้ แต่ถึงกระนั้นก็ตาม ในขณะที่ ผู้ให้บริการ LINQ มีข้อจำกัด การเปลี่ยนคำสั่ง SQL ไปเป็น LINQ ทำได้ง่ายกว่า fetchXML และ มันรองรับเอนทิตีที่มีผลผูกพันล่าช้า/ไดนามิก.

//create a list of random numbers
List<int> randomNumbers = new List<int>();

//declare a percentage of records you'd like to retrieve
double pctg = 0.07;

//use FetchXML to count the # of rows in the table
string fetchXml = @"<fetch aggregate='true'>
<entity name='salesorder'>
<attribute name='salesorderid' aggregate='count' alias='countIds' distinct='false' />
</entity>
</fetch>";
EntityCollection result = _service.RetrieveMultiple(new FetchExpression(fetchXml));
int rowCount = int.Parse(result.Entities[0].FormattedValues["countIds"].Replace(",", ""));

//initalize the random number list for paging
for (int i = 0; i < Math.Ceiling(pctg * rowCount); i++)
{
    randomNumbers.Add((new Random(unchecked((int)(DateTime.Now.Ticks >> i)))).Next(rowCount - 1));
}
randomNumbers.Sort();

//page through the rows one at a time until you have the number of rows you want
using (OrganizationServiceContext osc = new OrganizationServiceContext(_service))
{
    foreach (int r in randomNumbers)
    {
        foreach (var er in (from c in osc.CreateQuery("salesorder")
                            //not especially useful to use the orderby option as you can only order by entity attributes
                            //orderby c.GetAttributeValue<string>("name")
                            select new
                            {
                                name = c.GetAttributeValue<string>("name")
                            }).Skip(r).Take(1))
        {
            Console.WriteLine(er.name);
        }

    }
}
person Peter Majeed    schedule 17.09.2011
comment
ฉันไม่คิดว่าจะใช้คุกกี้เพจ - เป็นความคิดที่ดี! - person Josh Painter; 17.09.2011
comment
ข้อมูลที่น่าสนใจบางอย่างในคำตอบนี้ ฉันไม่รู้อย่างแน่นอนว่า LINQ สามารถใช้กับเอนทิตีไดนามิกในลักษณะที่แสดงในลิงก์ MSDN ของคุณ FetchXML อาจเป็นวิธีที่ดีกว่าในการดำเนินการนี้ ฉันจะต้องทดลองเพื่อดูว่าจะเปรียบเทียบประสิทธิภาพกับวิธีอื่นที่เสนอได้อย่างไร ขอบคุณมากสำหรับการตอบกลับ - person Alec; 19.09.2011