كيف يمكنني إنشاء جداول قاعدة البيانات من فئات C#؟

StackOverflow https://stackoverflow.com/questions/47239

  •  09-06-2019
  •  | 
  •  

سؤال

هل يعرف أحد طريقة لإنشاء جداول قاعدة البيانات تلقائيًا لفئة معينة؟أنا لا أبحث عن طبقة ثبات كاملة - لدي بالفعل حل للوصول إلى البيانات أستخدمه، ولكن فجأة أصبح عليّ تخزين الكثير من المعلومات من عدد كبير من الفئات ولا أريد حقًا إنشاءها كل هذه الجداول باليد.على سبيل المثال، بالنظر إلى الفئة التالية:

class Foo
{
    private string property1;
    public string Property1
    {
        get { return property1; }
        set { property1 = value; }
    }

    private int property2;
    public int Property2
    {
        get { return property2; }
        set { property2 = value; }
    }
}

أتوقع SQL التالي:

CREATE TABLE Foo
(
    Property1 VARCHAR(500),
    Property2 INT
)

أنا أتساءل أيضًا كيف يمكنك التعامل مع الأنواع المعقدة.على سبيل المثال، في الفصل المذكور سابقًا، إذا قمنا بتغيير ذلك ليصبح:

class Foo
{
    private string property1;
    public string Property1
    {
        get { return property1; }
        set { property1 = value; }
    }

    private System.Management.ManagementObject property2;
    public System.Management.ManagementObject Property2
    {
        get { return property2; }
        set { property2 = value; }
    }
}

كيف يمكنني التعامل مع هذا؟

لقد بحثت في محاولة إنشاء البرامج النصية لقاعدة البيانات تلقائيًا بنفسي باستخدام الانعكاس لتعداد خصائص كل فئة، ولكنها قديمة الطراز وأنواع البيانات المعقدة جعلتني في حيرة من أمري.

هل كانت مفيدة؟

المحلول

لقد تأخر الوقت حقًا، ولم أمضي سوى 10 دقائق تقريبًا في هذا الأمر، لذا فهو غير دقيق للغاية، ومع ذلك فهو يعمل وسيمنحك نقطة انطلاق جيدة:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace TableGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            List<TableClass> tables = new List<TableClass>();

            // Pass assembly name via argument
            Assembly a = Assembly.LoadFile(args[0]);

            Type[] types = a.GetTypes();

            // Get Types in the assembly.
            foreach (Type t in types)
            {
                TableClass tc = new TableClass(t);                
                tables.Add(tc);
            }

            // Create SQL for each table
            foreach (TableClass table in tables)
            {
                Console.WriteLine(table.CreateTableScript());
                Console.WriteLine();
            }

            // Total Hacked way to find FK relationships! Too lazy to fix right now
            foreach (TableClass table in tables)
            {
                foreach (KeyValuePair<String, Type> field in table.Fields)
                {
                    foreach (TableClass t2 in tables)
                    {
                        if (field.Value.Name == t2.ClassName)
                        {
                            // We have a FK Relationship!
                            Console.WriteLine("GO");
                            Console.WriteLine("ALTER TABLE " + table.ClassName + " WITH NOCHECK");
                            Console.WriteLine("ADD CONSTRAINT FK_" + field.Key + " FOREIGN KEY (" + field.Key + ") REFERENCES " + t2.ClassName + "(ID)");
                            Console.WriteLine("GO");

                        }
                    }
                }
            }
        }
    }

    public class TableClass
    {
        private List<KeyValuePair<String, Type>> _fieldInfo = new List<KeyValuePair<String, Type>>();
        private string _className = String.Empty;

        private Dictionary<Type, String> dataMapper
        {
            get
            {
                // Add the rest of your CLR Types to SQL Types mapping here
                Dictionary<Type, String> dataMapper = new Dictionary<Type, string>();
                dataMapper.Add(typeof(int), "BIGINT");
                dataMapper.Add(typeof(string), "NVARCHAR(500)");
                dataMapper.Add(typeof(bool), "BIT");
                dataMapper.Add(typeof(DateTime), "DATETIME");
                dataMapper.Add(typeof(float), "FLOAT");
                dataMapper.Add(typeof(decimal), "DECIMAL(18,0)");
                dataMapper.Add(typeof(Guid), "UNIQUEIDENTIFIER");

                return dataMapper;
            }
        }

        public List<KeyValuePair<String, Type>> Fields
        {
            get { return this._fieldInfo; }
            set { this._fieldInfo = value; }
        }

        public string ClassName
        {
            get { return this._className; }
            set { this._className = value; }
        }

        public TableClass(Type t)
        {
            this._className = t.Name;

            foreach (PropertyInfo p in t.GetProperties())
            {
                KeyValuePair<String, Type> field = new KeyValuePair<String, Type>(p.Name, p.PropertyType);

                this.Fields.Add(field);
            }
        }

        public string CreateTableScript()
        {
            System.Text.StringBuilder script = new StringBuilder();

            script.AppendLine("CREATE TABLE " + this.ClassName);
            script.AppendLine("(");
            script.AppendLine("\t ID BIGINT,");
            for (int i = 0; i < this.Fields.Count; i++)
            {
                KeyValuePair<String, Type> field = this.Fields[i];

                if (dataMapper.ContainsKey(field.Value))
                {
                    script.Append("\t " + field.Key + " " + dataMapper[field.Value]);
                }
                else
                {
                    // Complex Type? 
                    script.Append("\t " + field.Key + " BIGINT");
                }

                if (i != this.Fields.Count - 1)
                {
                    script.Append(",");
                }

                script.Append(Environment.NewLine);
            }

            script.AppendLine(")");

            return script.ToString();
        }
    }
}

أضع هذه الفئات في تجميع لاختبارها:

public class FakeDataClass
{
    public int AnInt
    {
        get;
        set;
    }

    public string AString
    {
        get;
        set;
    }

    public float AFloat
    {
        get;
        set;
    }

    public FKClass AFKReference
    {
        get;
        set;
    }
}

public class FKClass
    {
        public int AFKInt
        {
            get;
            set;
        }
    }

وقام بإنشاء SQL التالي:

CREATE TABLE FakeDataClass
(
         ID BIGINT,
         AnInt BIGINT,
         AString NVARCHAR(255),
         AFloat FLOAT,
         AFKReference BIGINT
)


CREATE TABLE FKClass
(
         ID BIGINT,
         AFKInt BIGINT
)


GO
ALTER TABLE FakeDataClass WITH NOCHECK
ADD CONSTRAINT FK_AFKReference FOREIGN KEY (AFKReference) REFERENCES FKClass(ID)
GO

بعض الأفكار الإضافية...أود أن أفكر في إضافة سمة مثل [SqlTable] إلى الفصول الدراسية الخاصة بك، وبهذه الطريقة يتم إنشاء جداول للفئات التي تريدها فقط.أيضًا، يمكن تنظيف هذا كثيرًا، وإصلاح الأخطاء، وتحسينها (FK Checker مجرد مزحة) وما إلى ذلك...فقط للبدء.

نصائح أخرى

@ جوناثان هولاند

واو، أعتقد أن هذا هو العمل الأكثر بدائية الذي رأيته على الإطلاق في منشور StackOverflow.أحسنت. لكن, ، بدلاً من إنشاء عبارات DDL كسلاسل، يجب عليك بالتأكيد استخدام التابع كائنات إدارة خادم SQL الفئات المقدمة مع SQL 2005

ديفيد هايدن لديه وظيفة بعنوان إنشاء جدول في SQL Server 2005 باستخدام كائنات إدارة C# وSQL Server (SMO) - إنشاء التعليمات البرمجية يشرح كيفية إنشاء جدول باستخدام SMO.الكائنات المكتوبة بقوة تجعل الأمر سهلاً باستخدام أساليب مثل:

// Create new table, called TestTable
Table newTable = new Table(db, "TestTable");

و

// Create a PK Index for the table
Index index = new Index(newTable, "PK_TestTable");
index.IndexKeyType = IndexKeyType.DriPrimaryKey;

VanOrman، إذا كنت تستخدم SQL 2005، فاجعل SMO جزءًا من الحل الخاص بك بالتأكيد.

جرب طريقة ملحق CreateSchema الخاصة بي للكائنات الموجودة في http://createschema.codeplex.com/

تقوم بإرجاع سلسلة لأي كائن يحتوي على البرامج النصية CREATE TABLE.

أعتقد أنه بالنسبة لأنواع البيانات المعقدة، يجب عليك توسيعها عن طريق تحديد طريقة ToDB() التي تحتفظ بتطبيقها الخاص لإنشاء الجداول في قاعدة البيانات، وبهذه الطريقة تصبح متكررة تلقائيًا.

اعتبارًا من عام 2016 (على ما أظن)، يمكنك استخدام Entity Framework 6 Code First لإنشاء مخطط SQL من فئات poco c# أو استخدام Database First لإنشاء كود c# من sql.التعليمات البرمجية أولاً إلى إرشادات قاعدة البيانات

بالنسبة للأنواع المعقدة، يمكنك تحويل كل نوع تصادفه بشكل متكرر إلى جدول خاص به ثم محاولة إدارة علاقات المفاتيح الخارجية.

قد ترغب أيضًا في التحديد المسبق أيّ سيتم أو لن يتم تحويل الفصول إلى جداول.أما بالنسبة للبيانات المعقدة التي تريد أن تنعكس في قاعدة البيانات دون تضخم المخطط، فيمكنك الحصول على جدول واحد أو أكثر لأنواع متنوعة.يستخدم هذا المثال ما يصل إلى 4:

CREATE TABLE MiscTypes /* may have to include standard types as well */
 ( TypeID INT,
   TypeName VARCHAR(...)
 )

CREATE TABLE MiscProperties
 ( PropertyID INT,
   DeclaringTypeID INT, /* FK to MiscTypes */
   PropertyName VARCHAR(...),
   ValueTypeID INT /* FK to MiscTypes */
 )

CREATE TABLE MiscData
 (  ObjectID INT,
    TypeID  INT
 )

CREATE TABLE MiscValues
 ( ObjectID INT, /* FK to MiscData*/
   PropertyID INT,
   Value VARCHAR(...)
 )

يمكنك القيام بالعكس، جدول قاعدة البيانات لفئات C# هنا:http://pureobjects.com/dbCode.aspx

أيضًا...ربما يمكنك استخدام بعض الأدوات مثل Visio (لست متأكدًا مما إذا كان Visio يفعل ذلك، ولكن أعتقد أنه يفعل ذلك) لإجراء هندسة عكسية لفئاتك في UML ثم استخدام UML لإنشاء مخطط قاعدة البيانات...أو ربما استخدم أداة مثل هذه http://www.tangiblearchitect.net/visual-studio/

أعلم أنك تبحث عن طبقة ثبات كاملة، لكن مهمة hbm2ddl الخاصة بـ NHibernate يمكنها القيام بذلك كخط واحد تقريبًا.

هناك مهمة نانت المتاحة لنسميها والتي قد تكون ذات فائدة.

دون سرعة الصوت هو أيضا خيار آخر.غالبًا ما أستخدمه لإنشاء فئات الكيانات التي يتم تعيينها لقاعدة البيانات.يحتوي على أداة مساعدة لسطر الأوامر تتيح لك تحديد الجداول والأنواع ومجموعة من الأشياء المفيدة الأخرى

جرب DaoliteMappingTool لـ .net.يمكن أن تساعدك على إنشاء الفصول الدراسية.تحميل النموذج هنا

يوجد تطبيق مجاني، Schematrix الذي يقوم بإنشاء فئات من قاعدة البيانات، تحقق مما إذا كان العكس يحدث أيضًا :) http://www.schematrix.com/products/schemacoder/download.aspx

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top