Pilih persentase rekaman menggunakan Entitas Dinamis CRM 2011

Saya sedang mengembangkan layanan yang menggunakan data CRM 2011 melalui entitas dinamis (seperti pada Microsoft.Xrm.Sdk.Entity, metode pengikatan akhir). Saya sengaja tidak menggunakan metode Xrm.cs (pengikatan awal) dalam upaya menjaga solusi saya tetap generik.

Selain itu, saya ingin menghindari koneksi ke database CRM secara langsung (misalnya EDMX) karena ini akan menghentikan solusi saya untuk digunakan untuk CRM yang dihosting (misalnya tanpa akses DB langsung).

Saya memiliki persyaratan (yang disederhanakan) berikut, saya benar-benar kesulitan dengan kriteria seleksi:

7% data secara acak perlu dipilih (dan diperbarui).

Dalam SQL, kriteria pemilihannya akan relatif mudah - Saya tahu cara memilih persentase catatan secara acak. Sesuatu seperti:

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

Ini bekerja dengan sempurna. Saya mengumpulkan yang setara dengan LINQ adalah seperti:

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

Namun ada masalah, saya tidak tahu cara menggunakan LINQ dengan entitas dinamis CRM 2011 - sebaliknya mereka bersikeras menggunakan beberapa kelas/sintaks QueryExpression yang membatasi, atau FetchXML, seperti yang terlihat di laman ini (MSDN).

Saya telah mengidentifikasi opsi berikut untuk memenuhi persyaratan ini:

  1. Dengan menggunakan entitas dinamis, kembalikan seluruh kumpulan data ke dalam Daftar, lalu cukup pilih pilihan acak berdasarkan indeks. Namun hal ini melibatkan pengembalian hingga 10.000 catatan melalui layanan data internet, yang mungkin lambat/tidak aman/dll.

  2. Gunakan pernyataan FetchXML. Sayangnya saya tidak tahu mengambilXML, jadi saya tidak tahu apakah mungkin melakukan hal-hal seperti COUNT, TOP, PERCENT atau NEWID().

  3. Gunakan Xrm.cs dan LINQ, atau gunakan Prosedur Tersimpan, atau tampilan SQL. Semua opsi ini berarti mengikat solusi ke konektivitas database langsung dan/atau pengikatan awal, yang mana hal ini tidak diinginkan.

  4. Katakan tidak kepada pelanggan.

Setiap saran akan sangat dihargai! Bisakah mengambilXML melakukan kueri ini? Apakah ada cara yang lebih baik untuk melakukan ini?


person Alec    schedule 15.09.2011    source sumber


Jawaban (2)


FetchXML tidak mendukung ini, jadi Anda memilih 1 atau 3. Dan Anda benar, 3 hanya akan berfungsi dalam versi On Premise, karena Anda tidak dapat terhubung langsung ke SQL dengan produk CRM Online. Namun, itulah yang akan saya pilih kecuali Anda benar-benar yakin pelanggan akan berpindah ke CRM Online. Jika Anda harus menggunakan 1, Anda setidaknya dapat membatasi kolom yang dikembalikan menjadi hanya GUID rekaman untuk mengurangi ukuran payload. Kemudian ketika Anda memilih catatan acak Anda, ambil saja kolom tambahannya jika diperlukan (tentu saja ini bisa menjadi lebih lambat karena "celoteh" tergantung pada berapa banyak catatan acak yang Anda hadapi).

person Josh Painter    schedule 15.09.2011
comment
Saya pikir pembuat persyaratan bersikeras bahwa solusinya dapat diterapkan pada lingkungan yang dihosting, jadi saya akan mengembalikan daftar id dan mengacaknya. Saya sudah memilih, akan menandai sebagai jawaban jika metode ini terbukti berhasil. Terima kasih :) - person Alec; 16.09.2011
comment
Saya dapat membuat ini berhasil menggunakan metode yang dijelaskan di atas; mengembalikan set lengkap sebagai daftar id saja, kemudian memilih data lengkap setelah melakukan pemilihan acak di memori. Jadi saya akan menempatkan ini sebagai jawabannya karena ini berfungsi, namun saya akan merekomendasikan siapa pun dengan persyaratan serupa harus membaca informasi dalam jawaban jamnap juga; Saya belum tahu solusi mana yang lebih efisien. - person Alec; 19.09.2011

Dynamics CRM 2011, pada saat ini, tidak dapat memberi Anda tingkat kekuatan kueri yang dapat diberikan oleh SQL dan penyedia LINQ lainnya, jadi saya sangat yakin Anda ingin mengatakan tidak kepada pelanggan dan pindah ke versi lokal jika dia menginginkan fleksibilitas semacam itu.

Oleh karena itu, varian metode #1 adalah, daripada mengambil semua baris sekaligus lalu memilih kumpulan acak Anda, ambil kumpulan acak dari entitas satu baris pada satu waktu hingga Anda mendapatkan jumlah baris yang Anda inginkan. Kelemahan dari metode ini adalah alih-alih satu panggilan ke DB, ada banyak panggilan, yang memperlambat kecepatan pengambilan secara keseluruhan. POC ada di bawah.

Adapun #2, saya yakin semua permintaan Anda dapat ditangani, dengan tingkat keberhasilan tertentu, menggunakan FetchXml. Faktanya, satu-satunya cara untuk mendapatkan data gabungan adalah dengan menggunakan FetchXml, dan juga mendukung halaman.

Adapun #3, SQL asli adalah pilihan terbaik Anda untuk mendapatkan semua yang Anda inginkan dari data Anda saat ini, namun meskipun demikian, sementara penyedia LINQ terbatas, jauh lebih mudah untuk mentransisikan pernyataan SQL ke LINQ daripada mengambilXML, dan itu mendukung entitas pengikatan akhir/dinamis.

//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
Saya tidak berpikir untuk menggunakan cookie paging - ide bagus! - person Josh Painter; 17.09.2011
comment
Beberapa informasi yang sangat menarik dalam jawaban ini, saya tentu tidak menyadari LINQ dapat digunakan dengan entitas dinamis seperti yang ditunjukkan di tautan MSDN Anda. FetchXML mungkin merupakan cara yang lebih baik untuk melakukan ini, saya harus bereksperimen untuk melihat perbandingan kinerjanya dengan metode lain yang diusulkan. Terima kasih banyak atas tanggapannya. - person Alec; 19.09.2011