en-UShe-IL
You are here:   Blog
Register   |  Login

Blog Archive:

Maximize
* Can be used in order to search for older blogs Entries

Search in blogs


Blog Categories:

Maximize
* Can be used in order to search for blogs Entries by Categories

Blog Tags:

Maximize
* Can be used in order to search for blogs by keywords

TNWikiSummit


Awared MVP

 


Microsoft® Community Contributor 


Microsoft® Community Contributor


 Read first, before you you use the blog! Maximize

Recent Entries

Minimize
יול4

Written by: ronen ariely
04/07/2013 09:29 RssIcon

הקדמה

במדריך קצר אני אראה כיצד אנחנו יכולים להכין אלמנט CLR בשרת SQL ולהחזיק פרמטר של ה CLR בזיכרון לשימוש משותף של כל הפניות ל CLR. לשם הדוגמה נכין פונקציה קטנה של COUNT. הפונקציה תשמש לנו לספור כמה פעמים פנו אל ה CLR שלנו מהרגע שהשרת התחיל לעבוד.המורכבות היא כמובן לא בחלק של הפיתוח קוד בדוט-נט, כי אם קשור בהגדרות שונות בשרת ה SQL על מנת לאפשר להריץ את הקוד.

על מנת לשתף פרמטר בין מופעים שונים של מחלקה ואיפוס הפרמטר שלנו עם ההרצה הראשונה של האלמנט, אנחנו נעשה שימוש בבנאי סטאטי (Static Constructors).

הקוד

ברירת המחדל של נקודת הגישה (נקודת ההתחלה) של ה CLR היא מתודה STATIC. למשל בקוד הבא נקודת הגישה תהיה במתודה Sql_User_Defined_Function. הסיבה זהה לחלוטין לכך שנקודת המוצא של אפליקציות שונות כמו אפליקציית CONSOLE היא מתודה STATIC. הרעיון הוא שבזמן הגישה לאפליקציה אנחנו רוצים להתחיל להפעיל אותה ישירות ללא צורך ביצירת מופע של אלמנט תחילה. אחרי הכל זה השורה הראשונה שצריכה לרוץ אז כיצד נפתח מופע אם לא היה לנו שום אפשרות להריץ קוד לפני נקודת הפתיחה?!? זה על רגל אחת בצורה שיטחית למה תמיד המתודה MAIN תהיה STATIC באפליקציית CONSOLE. כאמור דבר זה קורה בשימוש ב CLR. למשל אם אנחנו מפתחים מתודה מסויימת לשמש כפןנקציה סקלארית אז אנחנו לא רוצים לפתוח מופע חדש של אובייקט חדש בכל ריצה אלא רוצים להריץ את המתודה ישירות ללא מופע. לכן כדי לעבוד עם בנאי סטאטי יהיה עלינו לפתוח תחילה מופע של המחלקה שלנו, כך שנוכל לגשת אליו ואל הפרמטרים שלו בפרט בהמשך הקוד. 

//------------------------------------------------------------------------------
//
//      Copyright (c) Ronen Ariely.
//
//      this small clr function is only for demo on using STATIC builder under SQL CLR
//      i use this function to build a counter start on value 0 and increment by 1 each executing
//
//
//------------------------------------------------------------------------------
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
 
public partial class UserDefinedFunctions
{
 
    private static UserDefinedFunctions MyInstance;
    private static int MyCounter;
 
    static UserDefinedFunctions()
    {
        MyInstance = new UserDefinedFunctions();
        MyCounter = 0;
    }
 
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlInt32 Sql_User_Defined_Function(SqlInt32 originalAmount)
    {
        MyCounter = MyCounter + 1;
        SqlInt32 taxAmount = originalAmount + MyCounter;
        return originalAmount + taxAmount;
    }
}

.

הפעלת CLR ברמת השרת

שרתי SQL מובנים בצורה הכוללת אבטחה בסיסית. כך למשל על מנת להריץ קוד CLR עלינו לדרוש זאת במפורש ולפתוח את האפשרות בהגדרות השרת. אחרי הכל זה חלון באבטחה לאפשרות של הכנסת קוד זדוני.

-- Enabling CLR Integration\
-- To enable CLR integration, you must have ALTER SETTINGS server level permission
sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

.

קימפול הקוד

כאשר אנחנו ניגשים לפיתוח אפליקציה העומדת בפני עצמה אז הפנייה בין מופעים של מחלקות מהווה חלק אינטגרלי ופנימי לאפליקציה. לכן קימפול הקוד נעשה בצורה פשוטה. עם זה מטעמי אבטחה בשרתי SQL קימת מניעה בברירת המחדל לפנות ממופע אחד של אלמנט CLR אל מופע אחר או ממסד נתונים אחד למקור חיצוני כמו שרת חיצוני. פתיחת האפשרות לשימוש ב CLR לא תספיק לנו במקרה הנוכחי. אם ננסה להריץ בנאי סטאטי אז נקבל הודעה בסגנון:

Storing to a static field is not allowed in safe assemblies.

הודעה זו מרמזת לנו שחייבים לקמפל את הפרוייקט בצורה UNSAFE או EXTERNAL_ACCESS.

publish/deploy של הקוד אל שרת ה SQL

תחילה עלינו להגדיר מסד הנתונים שנוכל להכניס קוד שקומפל בצמצב UNSAFE וזאת נעשה בעזרת השאילתה הבאה:

alter database Database set trustworthy on
go


אם לא נבצע הגדרה הדרה זו אנחנו ניתקל בהודעת שגיאה מהצורה הבאה:

is not authorized for PERMISSION_SET = UNSAFE.  The assembly is authorized when either of the following is true: the database owner (DBO) has UNSAFE ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with UNSAFE ASSEMBLY permission.

עתה נוכל לחבר את האסמבלי שלנו את מסד הנתונים תוך כדי שימוש ברמז של PERMISSION_SET


create assembly MyClrStaticBuilderUse from N'C:\Project\ADONet\TranStress\bin\Debug\MyClrStaticBuilderUse.exe'
WITH PERMISSION_SET=UNSAFE
go


אם אתם מבצעים publish ישירות מפרוייקט של visual studio אז יש להקפיד בפרוייקט לבצע את ההגדרה המתאימה:

1. פתחו את חלון המאפיינים של הפרויקט
2. גשו אל הטאב של project setting
3. ליחצו על הכפתור database setting
4. בחלון שנפתח לכם עברו לטאב של Miscellaneos
סמנו ב V את תיבת הסימון ליד Trustworthy

* לעיתים לא תהיה לך ברירה אלא לבצע למסד הנתונים detach ו attach על מנת שההגדרות יכנסו לתוקף.

בדיקה והרצה של הפונקציה שלנו.

הריצו את הקוד הבא כמה פעמים שאתם רוצים תחת משתמשים שונים ואפליקציות שונות ותראו כיצד ה COUNTER שלנו מתקדם בכל הרצה ב1 בלי קשר למי הריץ אותו ומהיכן. זהוא אלמנט משותף של CLR ברמת הזכרון.

select dbo.Sql_User_Defined_Function(1)
GO

.

מקורות וחומר נוסף:

Introduction to SQL Server CLR Integration
http://msdn.microsoft.com/en-us/library/ms254498(v=vs.80).aspx