public class viewmodel1 { public model1 M1 { get; set; } public IEnumerable<model1> IEM1 { get; set; } }
تهیه گزارشات Crosstab به کمک LINQ - قسمت دوم
ممنون از مطلب مفیدتون.شما در اول این مطلب فرمودید :« اگر بازهی گزارشگیری به اختیار کاربر باشد» اما مثالهایی که زدین رو باید از اول دونست که چه ستونهایی رو میخواهیم.منطورم اینه که فرض کنید که اگر ما یک چک لیست برای ماههای سال داشته باشیم که کاربر بتونه هر ترتیبی از 12 ماه رو انتخاب کنه چکار باید کرد؟ با تشکر
ASP.NET MVC #10
آیا در مورد فرم لاگین نیز باید چنین کاری انجام شود و باید بتوان Url آنرا به همراه Id و کلمه عبور کاربر، برای استفاده بعدی ذخیره کرد؟ خیر؛ به دلایل امنیتی اینکار صحیح نیست.
در کل در این حالت خاص، به Url نهایی دقت کنید. نام کوئری استرینگهای آن باید با پارامترهای اکشن متد متناظر نهایی، تطابق داشته باشند. همچنین اگر بر روی اکشن متد آن، ویژگی HttpPost قرار گرفته باید حذف شود.
- Convert.Net
- Regular Expression Tester : که جهت تست Regexهای نوشته شده استفاده میشود.
- Encoding & Decoding : جهت تبدیل انواع رشتههای Encoded ویا Decoded به یکدیگر استفاده میشود و از html - url - EScape-js - Base64 - string و ... پشتیبانی میکند.
- Encryption & Decryption : جهت Encrypt و Decrypt انواع رشته استفاده میشود که از انکریپتورهای معروفی همچون AES - Rijndael - DES - SHA - TripleDES پشتیبانی میکند.
- Language Translation : یک دیکشنری Multi Language آنلاین در اختیار شما برای ترجمه متون قرار میدهد.
- C# & VB.Net Convertor : برای تبدیل کدهای C# به Vb و برعکس استفاده میشود و طبق تست هایی که روش به شخصه انجام دادم در اکثر موارد بدون خطا تا حدود 90 درصد تبدیلات رو به صورت موفق انجام میده ولی مانند سایر Convertorها با Lambda Expression کمی مشکل دارد.
- Xml & Json Browser : برای مشاهده و تبدیل Xml به Json و برعکس بسیار مفید است ..
- Linq Tester : برای تست کوئریهای Linq استفاده میشود . (برای استفاده از این امکان باید Roslyne روی سیستم شما نصب باشد)
- Database.Net
SQL Server 2000/2005/2008/2012/2014/Express/LocalDB SQL Server Compact 3.1/3.5/4.0 (*.sdf;*.*) SQL Azure 10/11 MS Access 97/2000/2002/2003 (*.mdb;*.mde;*.*), 2007/2010/2013 (*.accdb;*.accde;*.*) MS Excel 97/2000/2002/2003(*.xls;*.*), 2007/2010/2013 (*.xlsx;*.xlsm;*.xlsb;*.*) Firebird SuperServer/Embedded 1.5/2.0/2.1/2.5 (*.gdb;*.fdb;*.*) SQLite 3.x (*.db;*.db3;*.sqlite;*.*) MySQL 5.x, MariaDB 5.x/10.x PostgreSQL 8.x/9.x Oracle 10g/11g/12c IBM DB2 9.x/10.x IBM Informix 11.x/12.x Sybase ASE 15.x dBASE IV (*.dbf) Visual FoxPro (*.dbc) Data Sources (OleDB)(*.udl;*.*) ODBC DSN (Data Source Name)(*.dsn;*.*) OData (Open Data Protocol) v1/v2/v3/v4
- Resource.Net
سایر نرم افزارهای این تیم هم مانند نرم افزارهای معرفی شده بین کاربران محبوبیت زیادی کسب کرده اند که میتوانید برای کسب اطلاعات بیشتر و دانلود این نرم افزارها به وب سایت این تیم مراجعه فرمائید.
Microsoft.Data.Sqlite 2.1 منتشر شد
اگر علاقمند باشید که به آخرین نگارشهای Fluent NHibernate دسترسی داشته باشید، مکان اصلی نگهداری و Build آنها در سایت teamcity.codebetter.com میباشد. ثبت نام در آن رایگان است و سپس در آدرس ذیل میتوانید آخرین Build ها را مشاهده و دریافت کنید:
برای نمونه:
در این قسمت میخواهیم بیشتر در خصوص توابع مرتبط با ساختار سلسله مراتبی صحبت کنیم. برای آشنایی با این توابع و امکانات MDX Query، مقاله را با بررسی چندین Query دنبال خواهیم کرد.
بدست آوردن تمامی برادران یک سطح خاص :
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].parent.children on rows From [Adventure Works]
در کوئری بالا تمامی مشتریانی را که دارای کد پستی مشابه با کد پستی [Crystal Zheng]. میباشند، واکشی کرده ایم.
به عبارت دیگر با اعمال [Crystal Zheng].parent، به کد پستی مشتری دسترسی پیدا کرده ایم (برای درک بیشتر در زیر ساختار سلسله مراتبی موقعیت جغرافیایی مشتریان را ببینید) و سپس با اعمال .children به تمامی مشتریان موجود در آن کد پستی رسیده ایم؛ که عملا همان برادران [Crystal Zheng] می باشند.
نتیجه کوئری بالا در زیر نمایش داده شده است
راه بهتر برای بدست آوردن تمامی برادران یک سطح، استفاده از تابع siblings میباشد.
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].siblings on rows From [Adventure Works]
کوئریهای بالا جواب یکسانی را بر میگردانند. به عبارت دیگر تابع siblings عملا کار دو تابع parent.children را انجام میدهد
برای بدست آوردن برادر ارشد به صورت زیر عمل میکنیم (اولین بچه در ساختار سلسله مراتبی)
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].parent.firstchild on rows From [Adventure Works]
و یا از تابع زیر استفاده میکنیم
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].firstsibling on rows From [Adventure Works]
هر دو کوئری به جواب یکسان خواهند رسید.
و برای بدست آوردن آخرین برادر در ساختار سلسله مراتبی (برادر ته تغاری) از دو روش زیر میتوان استفاده کرد.
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].parent.lastchild on rows From [Adventure Works]
یا
Select [Measures].[Internet Sales Amount] on columns, [Customer].[Customer Geography].[Customer].[Crystal Zheng].lastsibling on rows From [Adventure Works]
برای توضیح بیشتر میتوان اضافه کرد که در کوئری بالا میزان فروش اینترنتی را برای آخرین مشتری در موقعیت جغرافیایی مشتری با نام [Crystal Zheng] واکشی شده است.
حال تصور کنید بخواهیم میزان فروش اینترنتی را برای تمامی مشتریان ایالت [Yveline] بدست بیاوریم. در این صورت MDX Query به شکل زیر خواهد بود
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[State-Province].[Yveline] ,[Customer].[Customer Geography].[Customer] )on rows From [Adventure Works]
تابع descendants دارای دو پارامتر میباشد. اولی برای مشخص نمودن شروع و مبدا در ساختار سلسله مراتبی و دومین برای مشخص کردن سطح واکشی در ساختار سلسله مراتبی میباشد. به عبارت دیگر در کوئری بالا تمامی زاد و رود ایالت [Yveline] در سطح شهر واکشی شده است و میزان فروش اینترنتی آن نمایش داده شده است.
در زیر یک کوئری ترکیبی با استفاده از دو تابع ancestor و descendants نوشته شده است.
Select [Measures].[Internet Sales Amount] on columns, descendants( ancestor( [Customer].[Customer Geography].[Customer].[Crystal Zheng], [Customer].[Customer Geography].[State-Province] ) ,[Customer].[Customer Geography].[Customer] )on rows From [Adventure Works]
در اینجا ابتدا جد یک مشتری در سطح ایالت بدست آمده سپس زاد و رود آن در سطح مشتری بدست می آید .
برای بدست آوردن فروش اینترنتی تمامی شهرهای کشور فرانسه میتوانیم به صورت زیر عمل کنیم.
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], [Customer].[Customer Geography].[City] ) on rows From [Adventure Works]
تابع descendants دارای یک پارامتر سوم هم میباشد که مشخص کنندهی میزان واکشی سطوح میباشد و به صورت پیش فرض Self میباشد. بنابر این کوئری بالا و پایین ، نتیجه یکسان خواهند داشت
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], [Customer].[Customer Geography].[City], self )on rows From [Adventure Works]
حال اگر بخواهیم فروش اینترنتی را برای تمامی زاد و رود کشور فرانسه از سطح شهر به پایین واکشی کنیم داریم :
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], [Customer].[Customer Geography].[City], self_and_after ) on rows From [Adventure Works]
در این حالات تمامی زاد و رود کشور فرانسه از سطح شهر به پایین در خروجی قرار می گیرد .به این صورت که ابتدا اولین شهر می آید؛ سپس اولین کد پستی در آن شهر و بعد تمامی مشتری های آن کد پستی و بعد کد پستی بعدی و ...
به دست آوردن تمامی زاد و رود فرانسه از سطح بعد از شهر .
به عبارت دیگر ، خروجی باتوجه به ساختار سلسله مراتبی تعریف شده عبارت است از کد پستی و تمام مشتریان آن کد پستی و سپس کد پستی بعدی .
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], [Customer].[Customer Geography].[City], after )on rows From [Adventure Works]
در کوئری فوق، خود شهر در خروجی نمایش داده نمیشود.
به دست آوردن زاد و رود فرانسه تا یک سطح قبل از شهر .
در این حالت فرانسه و تمامی ایالت های آن در خروجی آورده می شود .
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], [Customer].[Customer Geography].[City], before )on rows From [Adventure Works]
همچنین میتوان دومین پارامتر تابع را به صورت عدد وارد کرد و این عدد بیانگر تعداد سطح پایینتر از پارامتر اول در ساختار سلسله مراتبی میباشد.
به عنوان مثال :
Select [Measures].[Internet Sales Amount] on columns, descendants( [Customer].[Customer Geography].[Country].[France], 2, before ) on rows From [Adventure Works]
در این حالت فرانسه و تمامی ایالت های آن در خروجی قرار می گیرد .
در ابتدا دو سطح ار کشور پایین می رویم و به شهر می رسیم و بعد زاد و رود فرانسه تا یکی قبل از شهر را بر می گرداند .
در قسمتهای بعدی در خصوص دیگر توابع مرتبط با ساختارهای سلسله مراتبی، توضیحاتی را ارایه خواهم کرد.
روشهایی که قرار هست در ادامه توضیح داده شوند بر اساس کوئری بازگشتی میباشند. الگوریتمهای متنوعی بر اساس recursive CTE برای حل این مساله خلق شده اند. که من تنها به دو روش آن اکتفا میکنم.
Recursive CTE در نسخهی 2005 به SQL Server اضافه شده است. توسط این تکنیک مسائل پیچیده و گوناگونی را میتوان بسادگی حل نمود. مخصوصا مسائلی که ماهیت بازگشتی دارند مثل پیمایش یک درخت یا پیمایش یک گراف وزن دار.
روش اول:
یک کوئری بازگشتی دارای دو بخش هست به نامهای Anchor و recursive. در بخش دوم کوئری باز خودش را فراخوانی میکند تا به داده هایی که در مرحله قبل تولید شده اند دسترسی پیدا کند در اولین فراخوانی توسط عضو recursive، دادههای تولید شده در قسمت Anchor قابل دسترسی هستند. در قسمت دوم، کوئری آنقدر خود را فراخوانی میکند تا دیگر سطری از مرحله قبل وجود نداشته باشد که به آن مراجعه کند.
توضیح تکنیک:
در گام اول اندیس شروع و پایان کلمه اول را بدست میآوریم.
سپس در گام بعدی از اندیس پایان کلمه قبلی به عنوان اندیس شروع کلمه جدید استفاده میکنیم.
و اندیس پایان کلمه توسط تابع charindex بدست میآید.
کوئری تا زمانی ادامه پیدا میکند که کلمه برای تجزیه کردن در رشته باقی مانده باشد. فقط فراموش نکنید که حتما باید آخر عبارت یک کارکتر space داشته باشید.
DECLARE @S VARCHAR(50)='I am a student I go to school '; WITH CTE AS ( SELECT 1 rnk, 1 start, CHARINDEX(' ', @s) - 1 ed UNION ALL SELECT rnk + 1, ed + 2, CHARINDEX(' ', @s, ed + 2) - 1 FROM CTE WHERE CHARINDEX(' ', @s, ed + 2) > 0 ) SELECT rnk, SUBSTRING(@s, start, ed - start + 1) AS word FROM CTE /* Result rnk word ----------- ------- 1 I 2 am 3 a 4 student 5 I 6 go 7 to 8 school */
روش دوم:
در این روش در همان CTE عبارت تجزیه میشود و عمل تفکیک به مرحله بعدی واگذار نمیشود،
در گام اول، اولین کلمه انتخاب میشود. و سپس آن کلمه از رشته حذف میشود. با این روش همیشه اندیس شروع کلمه برابر با 1 خواهد بود و اندیس پایان کلمه توسط تابع charindex بدست خواهد آمد.
در گام بعدی اولین کلمه موجود در رشته ای که قبلا اولین کلمه از آن جدا شده است بدست میآید و باز مثل قبلی کلمه انتخاب شده از رشته جدا شده و رشته برش یافته به مرحله بعد منتقل میشود.
در این روش مثل روش قبلی آخر عبارتی که قرار هست تجزیه شود باید یک کارکتر خالی وجود داشته باشد.
DECLARE @a VARCHAR(50)='I am a student I go to school '; WITH MyWords(ranking, word, string) AS( SELECT 1, CAST(SUBSTRING(@a, 1, CHARINDEX(' ', @a) - 1) AS VARCHAR(25)), STUFF(@a, 1, CHARINDEX(' ', @a), '') UNION ALL SELECT ranking + 1, CAST(SUBSTRING(string, 1, CHARINDEX(' ', string) - 1) AS VARCHAR(25)), STUFF(string, 1, CHARINDEX(' ', string), '') FROM MyWords WHERE CHARINDEX(' ', string) > 0 ) SELECT ranking, word FROM MyWords;
ranking word ----------- ------------------------- 1 I 2 am 3 a 4 student 5 I 6 go 7 to 8 school
برای بدست آوردن تعداد تکرار یک کلمه در یک رشته مراحل زیر را طی کنید:
1- اگر در رشته بین کلمات تنها یک فاصله بود آن را به دو فاصله تبدیل کنید.
2- اگر ابتدا و انتهای رشته فاصله وجود نداشت فاصله اضافه کنید.
3- طول رشته بعد از حذف کلمات مشابه کلمه مورد نظر را از طول رشته تفریق کنید و عدد حاصل را تقسیم به طول کلمه مورد نظر کنید
DECLARE @S VARCHAR(50) = 'ali ali ali ali hasan reza ali javad reza reza' SELECT D.value, E.cnt FROM (VALUES ('ali'), ('hasan'), ('reza'), ('javad')) AS D(value) CROSS APPLY (SELECT ' ' + REPLACE(@s, ' ', ' ') + ' ') AS C(String) CROSS APPLY (SELECT (LEN(String) - LEN(REPLACE(String, ' ' + D.value + ' ', ''))) / (LEN(D.value) + 2)) AS E(cnt) ORDER BY cnt DESC;
خروجی کوئری فوق برابر است با:
<script src="jquery-1.8.0.min.js" type="text/javascript"></script> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("feeds", "1"); function initializeda() { var feed = new google.feeds.Feed("http://www.drupaleasy.ir/rss.xml"); feed.setNumEntries(5); feed.setResultFormat(google.feeds.Feed.JSON_FORMAT); feed.load(function (result) { if (!result.error) { for (var i = 0; i < result.feed.entries.length; i++) { var entry = result.feed.entries[i]; $('#drupaleasy ul').append('<li><a href="' + entry.link + '">' + entry.title + '</a></li>'); } } }); } google.setOnLoadCallback(initializeda); </script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
google.load("feeds", "1");
var feed = new google.feeds.Feed("http://www.drupaleasy.ir/rss.xml");
feed.setNumEntries(5); feed.setResultFormat(google.feeds.Feed.JSON_FORMAT);
feed.load(function (result) { if (!result.error) { for (var i = 0; i < result.feed.entries.length; i++) { var entry = result.feed.entries[i]; $('#drupaleasy ul').append('<li><a href="' + entry.link + '">' + entry.title + '</a></li>'); } } });
<div id="drupaleasy" class="feeds"> <span>DrupalEasy.ir</span> <ul> </ul> <a href="http://drupaleasy.ir">more</a> </div>
.feeds { float: right; background-color: rgba(234, 242, 243, 0.73); margin: 5px; border-radius: 20px; padding: 8px; width: 293px; height: 217px; border: 1px solid #293883; } #drupaleasy ul { list-style-image: url("img/drupal.png"); }