• דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

סקריפט ליצירה אוטומטית של מחלקות C# מבסיס נתונים ב-SQL Server

מתוזמן נעוץ נעול הועבר תכנות
6 פוסטים 4 כותבים 72 צפיות
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • OdedDvirO מחובר
    OdedDvirO מחובר
    OdedDvir
    כתב ב נערך לאחרונה על ידי
    #1

    טוב, אז אני מניח שהכותרת די ברורה:
    כידוע, לפי הספר, כל טבלה ב-SQL קלאסי אמורה לייצג יישות (Entity), שבד"כ מיוצגת על ידי מחלקה (Class) תואמת בתוכנה.
    כל פעם שאני בא להמיר איזה פרוייקט מאקסס ל-C# אני נתקל בעבודה הסיזיפית הזו.

    חיפשתי פיתרון שיתן לי ליצור בקלות את כל המודלים של הנתונים מתוך הגדרות הטבלאות.

    יש איזו דרך מתוסבכת לעשות זאת על ידי EntityFramework, אבל עד עכשיו הייתי משתמש באתר CodVerter ליצירה של מחלקה על ידי הכנסה של הגדרות הסקריפט SQL שיוצר אותה,

    ז"א אם אני מכניס את הסקריפט הבא:

    CREATE TABLE [dbo].[Sender] (
        [SenderID]   INT           NOT NULL,
        [SenderName] NVARCHAR (50) NOT NULL
    );
    

    אני מקבל בתמורה:

    public class Sender
    {
    	public int SenderID {get;set;}
    	public string SenderName {get;set;}
    }
    

    וזה כמובן נחמד כשמדובר בכמה טבלאות בודדות, אבל כשצריך להעביר עשרות טבלאות, זה מאוד לא נוח.

    אבל היום גיליתי סקריפט נהדר ב-CodeProject, שיוצר בבת אחת את כל הקלאסים עבור כל הטבלאות ב-DB, וחסך לי כאב ראש גדול.

    אז הנה הוא לפניכם (בתיקון שגיאה קטנה שהיתה במקור): פשוט לפתוח את בסיס הנתונים ב-SSMS, להדביק את הסקריפט הבא, להריץ, לקבל את כל הקלאסים על מגש של כסף, ולהגיש חם עם כוס נס-קפה:

    SET NOCOUNT ON;  
      
    DECLARE @table_name NVARCHAR(250), @message VARCHAR(80);  
      
    DECLARE table_cursor CURSOR FOR   
    select distinct tab.name as table_name
    from sys.tables as tab
        inner join sys.columns as col on tab.object_id = col.object_id
        left join sys.types as t on col.user_type_id = t.user_type_id
    order by table_name;  
      
    OPEN table_cursor  
      
    FETCH NEXT FROM table_cursor   
    INTO @table_name  
      
    WHILE @@FETCH_STATUS = 0  
    BEGIN  
        PRINT ' '  
        --SELECT @message = 'Table Name: ' +   
        --    @table_name  
      
        --PRINT @message  
      
        --declare @TableName sysname = 'TableName'
        declare @Result varchar(max) = 'public class ' + @table_name + '
    {'
    
        select @Result = @Result + '
        public ' + ColumnType + NullableSign + ' ' + ColumnName + ' { get; set; }'
        from
        (
        select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
        when 'bigint' then 'long'
        when 'binary' then 'byte[]'
        when 'bit' then 'bool'
        when 'char' then 'string'
        when 'date' then 'DateTime'
        when 'datetime' then 'DateTime'
        when 'datetime2' then 'DateTime'
        when 'datetimeoffset' then 'DateTimeOffset'
        when 'decimal' then 'decimal'
        when 'float' then 'float'
        when 'image' then 'byte[]'
        when 'int' then 'int'
        when 'money' then 'decimal'
        when 'nchar' then 'char'
        when 'ntext' then 'string'
        when 'numeric' then 'decimal'
        when 'nvarchar' then 'string'
        when 'real' then 'double'
        when 'smalldatetime' then 'DateTime'
        when 'smallint' then 'short'
        when 'smallmoney' then 'decimal'
        when 'text' then 'string'
        when 'time' then 'TimeSpan'
        when 'timestamp' then 'DateTime'
        when 'tinyint' then 'byte'
        when 'uniqueidentifier' then 'Guid'
        when 'varbinary' then 'byte[]'
        when 'varchar' then 'string'
        else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
        when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 
        'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 
        'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 
        'time', 'tinyint', 'uniqueidentifier') 
        then '?' 
        else '' 
        end NullableSign
        from sys.columns col
        join sys.types typ on
        col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
        where object_id = object_id(@table_name)
        ) t
        order by ColumnId
    
        set @Result = @Result  + '
    }'
    
        print @Result
      
        FETCH NEXT FROM table_cursor   
        INTO @table_name  
    END   
    CLOSE table_cursor;  
    DEALLOCATE table_cursor;  
    

    נ.ב. יתכן ואני מגלה את אמריקה ויש דרך יותר קלה\סטנדרטית, אם כן - אשמח לשמוע.

    חגיח רפאלר dovidD 3 תגובות תגובה אחרונה
    4
  • חגיח מנותק
    חגיח מנותק
    חגי
    השיב לOdedDvir ב נערך לאחרונה על ידי
    #2

    @OdedDvir
    אתה יכול לגרום לentity framework ליצור את המחלקות הללו בשבילך ב-.net הרגיל (לא core), וזה גם מגיע עם עורך ויזואלי לקשרים בין טבלאות.
    בcore אין את כל הדברים השווים האלה בגלל שזאת הקידמה, כך מסתבר...

    dovidD תגובה 1 תגובה אחרונה
    2
  • רפאלר מנותק
    רפאלר מנותק
    רפאל
    השיב לOdedDvir ב נערך לאחרונה על ידי רפאל
    #3

    הדרך הרשמית לבצע זאת בEntity Framework Core היא שימוש בפקודה dotnet ef dbcontext scaffold, אשר תיצור את הDbContext ואת הEntities בצורה אוטומטית, אחת מהמעלות הבולטות של השימוש בפקודה היא השינוי של שמות המחלקות והProperties כך שיתאימו למוסכמות של C# (ניתן לבטל את הפיצר באמצעות הפרמטר use-database-names--) כמו כן באמצעות הכלי ניתן להגדיר דברים רבים נוספים הקשורים ליצירה של המחלקות.

    דוגמא בסיסית (שימוש בlocaldb):

    dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DatabaseName" Microsoft.EntityFrameworkCore.SqlServer
    

    דוגמא נרחבת:

    dotnet ef dbcontext scaffold "Server=ServerName; Database=DatabaseName; User Id=UserId; Password=Password" Microsoft.EntityFrameworkCore.SqlServer   --context=DbContext --context-dir  DbDir --data-annotations --output-dir DbDir/Entities
    

    לשימוש בכלי מומלץ להתקינו גלובלית:

    dotnet tool install --global dotnet-ef
    
    תגובה 1 תגובה אחרונה
    3
  • dovidD מנותק
    dovidD מנותק
    dovid ניהול
    השיב לחגי ב נערך לאחרונה על ידי
    #4

    @חגי הוא הזכיר זאת, רק תיאר את זה כדרך מסובכת.
    זה אכן לא מסובך, זה תבנית T4 של ייצור קוד, אבל זה אכן הרבה יותר קל הקוד שהובא פה. אבל לשינויים תכופים הוא פחות נח (בT4 זה בלחיצת כפתור ימני וריענון).

    אפשר ליצור קשר dovid@tchumim.com

    OdedDvirO תגובה 1 תגובה אחרונה
    3
  • dovidD מנותק
    dovidD מנותק
    dovid ניהול
    השיב לOdedDvir ב נערך לאחרונה על ידי
    #5

    @OdedDvir אמר בסקריפט ליצירה אוטומטית של מחלקות C# מבסיס נתונים ב-SQL Server:

    כידוע, לפי הספר, כל טבלה ב-SQL קלאסי אמורה לייצג יישות (Entity), שבד"כ מיוצגת על ידי מחלקה

    זה לא בהכרח. זה נכון אם אתה משתמש בORM או שאתה חובב טיפוסיות קשוחה.

    אפשר ליצור קשר dovid@tchumim.com

    תגובה 1 תגובה אחרונה
    2
  • OdedDvirO מחובר
    OdedDvirO מחובר
    OdedDvir
    השיב לdovid ב נערך לאחרונה על ידי
    #6

    תודה @רפאל על הדוגמא המפורטת, כהרגלך הטוב!

    @dovid @חגי, אם כוונתכם למקור שציינתי, אני משתמש ב-Core, והתקנת התבנית DAO.Entity בכלל לא הופיעה לי בתור אופציה. (שמא זה בגלל התמיכה רק ב Framework הישן) זה מה שסיבך עבורי את העניין...

    @dovid אמר בסקריפט ליצירה אוטומטית של מחלקות C# מבסיס נתונים ב-SQL Server:

    זה נכון אם אתה משתמש בORM או שאתה חובב טיפוסיות קשוחה.

    מודה באשמה...

    תגובה 1 תגובה אחרונה
    3

  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.
  • פוסט ראשון
    פוסט אחרון
0
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.