簡體   English   中英

將C#類(類庫)轉換為SQL DDL(表)

[英]Convert C# classes (class library) to SQL DDL (tables)

我必須將一組C#類(類庫)轉換為SQL Server使用的SQL表,以便數據可以存儲在數據庫中並通過數據庫進行操作。

問題是這些類的數量很大(超過1000個類),並且需要很長時間才能手動設置這樣的數據庫模式(表,索引,存儲過程等) - 更不用說類層次結構了我需要保持。

所以,問題是:

有沒有一個工具可以幫助我從C#類庫創建數據庫模式?

我不是在尋找完美的工具(但如果有這樣的工具我會很高興知道),但是對於一個能幫助我至少創造一個起點的工具。

請注意,我更傾向於您建議的解決方案來引用.NET Framework 2.0版,並基於傳統實踐(T-SQL代碼如: CREATE TABLE ... ),盡管歡迎提出每個建議。

如果您可以使用Visual Studio 2010 v4.0框架,則可以使用“Model First”和實體框架生成腳本。 這顯然對v2.0沒有幫助,但我認為值得一提。

“模型優先”功能允許您在實體設計器中設計概念(CSDL)模型,然后生成存儲(SSDL)模型,以及它們之間的映射(MSL)。 此外,我們還生成T-SQL腳本以便為您創建數據庫。 要運行Model First向導,只需右鍵單擊Entity Designer表面,然后選擇“從Model中生成數據庫...”。 這里有一個深入的博客文章在這里 另外,請查看此文章

我不知道任何工具,但對於那么多的表,或許值得編寫一個使用Reflection的小工具來獲取所有屬性並吐出創建表語句,並定義列名和類型。 一個完美的腳本很難實現,但正如你的問題所述,這可以為你提供一個非常好的起點,然后調整字段類型和大小。

“Code First”實體框架中有一個新的CTP。 在編寫更多代碼之后,您可以使用它直接從代碼生成數據庫。

創建1000個表還需要一段時間。

如果類結構是關系型的並且轉換為SQL Create Table或EF模型相對簡單,那么您可以編寫自己的代碼生成腳本來創建.edmx或SQL。

您可以使用T4或CodeDom,它可能比手動創建1000個表需要更少的時間。

編輯:當我第一次寫回答時,我忘記了這一點。 前段時間我看到Rob Conery關於Subsonic Simple Repositroy的截屏視頻。 Simple Repository允許您將對象插入到DB中,如果沒有表,則為您創建一個對象。

http://subsonicproject.com/docs/Using_SimpleRepository上查看視頻

大多數對象關系映射工具都包含一個基於映射類創建數據庫模式的選項。

以下是使用NHibernate和Fluent NHibernate完成此操作的完整示例。 這是一個獨立的C#控制台應用程序,它將映射C#業務對象的集合並基於它們創建數據庫架構。

兩個重要的警告:

  1. NHibernate(和Fluent NH)要求必須將業務對象的所有屬性和方法聲明為虛擬; 這可能需要修改一些現有代碼。
  2. 不要對活動的數據庫運行這段代碼, 永遠 -默認情況下,它為您的所有現有表DROP語句並重新創建它們。 它會殺死你的所有數據,這會讓你傷心。 你被警告了。

這是program.cs 請注意三個名稱空間 - 一個包含程序本身,一個包含實體,另一個包含Fluent NHibernate的映射覆蓋示例(如果您的對象不遵循內置映射約定,則很有用)

using System;
using System.Collections.Generic;
using System.IO;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using Schematica.Entities;

namespace Schematica.ConsoleApp {

    class Program {

        const string SCHEMA_FILENAME = "schema.sql";
        const string CONNECTION_STRING = "Data Source=spotgeek;Initial Catalog=dylanhax;Integrated Security=True";

        public static void Main(string[] args) {

            if (File.Exists(SCHEMA_FILENAME)) File.Delete(SCHEMA_FILENAME);

            ConfigureNHibernate(CONNECTION_STRING, MapEntities);

            Console.WriteLine("Exported schema to " + (Path.GetFullPath(SCHEMA_FILENAME)));
            Console.ReadKey(false);
        }


        private static void MapEntities(MappingConfiguration map) {

            // Notice how we're constraining the auto-mapping to only map those entities
            // whose namespace ends with "Entities" - otherwise it'll try to 
            // auto-map every class in the same assembly as Customer.

            map.AutoMappings.Add(
                AutoMap.AssemblyOf<Customer>()
                .Where(type => type.Namespace.EndsWith("Entities"))
                .UseOverridesFromAssemblyOf<Customer>());
        }

        private static Configuration ConfigureNHibernate(string connectionString, Action<MappingConfiguration> mapper) {
            var database = Fluently.Configure().Database(MsSqlConfiguration.MsSql2005.ConnectionString(connectionString));
            return (database.Mappings(mapper).ExposeConfiguration(ExportSchema).BuildConfiguration());
        }

        private static void WriteScriptToFile(string schemaScript) {
            File.AppendAllText(SCHEMA_FILENAME, schemaScript);
        }

        private static void ExportSchema(Configuration config) {
            bool createObjectsInDatabase = false;
            new SchemaExport(config).Create(WriteScriptToFile, createObjectsInDatabase);
        }
    }
}

// This demonstrates how to override auto-mapped properties if your objects don't 
// adhere to FluentNH mapping conventions.
namespace Schematica.Mappings {
    public class ProductMappingOverrides : IAutoMappingOverride<Product> {
        public void Override(AutoMapping<Product> map) {

            // This specifies that Product uses ProductCode as the primary key, 
            // instead of the default Id field.
            map.Id(product => product.ProductCode);
        }
    }
}


// This is the namespace containing your business objects - the things you want to export to your database.
namespace Schematica.Entities {
    public class Customer {
        public virtual int Id { get; set; }
        public virtual string Forenames { get; set; }
        public virtual string Surname { get; set; }
    }

    public class Product {
        public virtual Guid ProductCode { get; set; }
        public virtual string Description { get; set; }
    }

    public class Order {
        public virtual int Id { get; set; }
        private IList<Product> products = new List<Product>();
        public virtual IList<Product> Products {
            get { return products; }
            set { products = value; }
        }
        public virtual Customer Customer { get; set; }
    }
}

以下是通過上面的代碼導出到schema.sql的內容:

if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FK952904EBD5E0278A]') AND parent_object_id = OBJECT_ID('[Product]'))
    alter table [Product]  drop constraint FK952904EBD5E0278A

if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FKD1436656C882C014]') AND parent_object_id = OBJECT_ID('[Order]'))
    alter table [Order]  drop constraint FKD1436656C882C014

if exists (select * from dbo.sysobjects where id = object_id(N'[Customer]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [Customer]
if exists (select * from dbo.sysobjects where id = object_id(N'[Product]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [Product]
if exists (select * from dbo.sysobjects where id = object_id(N'[Order]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [Order]

create table [Customer] (
    Id INT IDENTITY NOT NULL,
   Forenames NVARCHAR(255) null,
   Surname NVARCHAR(255) null,
   primary key (Id)
)

create table [Product] (
    ProductCode UNIQUEIDENTIFIER not null,
   Description NVARCHAR(255) null,
   Order_id INT null,
   primary key (ProductCode)
)

create table [Order] (
    Id INT IDENTITY NOT NULL,
   Customer_id INT null,
   primary key (Id)
)

alter table [Product] 
    add constraint FK952904EBD5E0278A 
    foreign key (Order_id) 
    references [Order]

alter table [Order] 
    add constraint FKD1436656C882C014 
    foreign key (Customer_id) 
    references [Customer]

只是為了擴展其他人所說的內容 - 大多數ORM類型的工具都具有模型優先功能。 與EF4,NHibernate和Telerik Open Access非常相似,Subsonic( http://www.subsonicproject.com/ )具有可以從類生成表的簡單存儲庫模式。

這里的另一個選擇是編寫一個簡單的基於反射的工具來遍歷您的類。


雖然您沒有問,但我對您的數據訪問需求感到好奇。 我們為三個主要任務雇用關系數據庫:持久性,有效的信息檢索和聲明性參照完整性(例如外鍵)。 僅僅為每個班級創建一個表只是成功的一半。

你有大量的數據(即100的演出或多太字節)? 很多讀物? 很多寫作? 這些類有自然的主鍵嗎? 代理鍵? 您的課程是否定義了彼此之間的關系(即EmployeesFactories工作)。

課程有很多領域嗎? 您是否有任何元數據表明數據類型具有精確性,即不僅僅是string NameName最多可以包含80個字符並且不可為空? 您是否只需要存儲英語,或者您是否使用需要像普通話這樣的擴展字符集的語言? 如果您沒有指示精度的方法,那么您的數據庫最終會出現嚴重的行(或可能很寬)。 許多數據庫將最大行大小限制在8k-64k范圍內。 寬行影響讀寫性能。 使用text字段可能會限制頁面大小限制,但會導致更高的讀取性能。

與實現數據庫結構一樣重要的是索引它並使用參照完整性。 課程/表格的數量會隨着時間的推移而增長嗎? 也許更抽象的結構與更少的表是適當的。

只是我的2c。 希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM