如何从 C# 类生成数据库表?
Posted
技术标签:
【中文标题】如何从 C# 类生成数据库表?【英文标题】:How can I generate database tables from C# classes? 【发布时间】:2010-09-08 00:22:07 【问题描述】:有人知道为给定类自动生成数据库表的方法吗?我不是在寻找一个完整的持久层——我已经有一个正在使用的数据访问解决方案,但是我突然不得不存储来自大量类的大量信息,我真的不想创建所有这些表都是手工制作的。例如,给定以下类:
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;
我该如何处理?
我曾尝试自己使用反射来枚举每个类的属性来自动生成数据库脚本,但它很笨重,而且复杂的数据类型让我很困惑。
【问题讨论】:
即使我正在寻找相同的解决方案。你能帮我从类的生成sql表吗? ? 【参考方案1】:真的很晚了,我只花了大约 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 检查器是个笑话)等等......只是为了让你开始。
【讨论】:
我不敢相信我在 2016 年使用过这个。非常感谢! 2019 - 签到 这是从 C# 类创建表的绝佳起点。如果有人需要有关 SQL 数据类型到 CLR 类型映射的文档,请参阅 Microsoft 的链接。 docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/linq/… 如何通过参数传递程序集名称?【参考方案2】:@乔纳森·霍兰德
哇,我认为这是我在 *** 帖子中看到的最原始的工作。做得好。 但是,您绝对应该使用 SQL 2005 引入的 SQL Server Management Objects 类,而不是将 DDL 语句构造为字符串。
David Hayden 有一篇题为 Create Table in SQL Server 2005 Using C# and SQL Server Management Objects (SMO) - Code Generation 的帖子介绍了如何使用 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 作为您解决方案的一部分。
【讨论】:
很好的建议。以前从未见过。您的链接已损坏,但这是另一个示例:codeproject.com/Articles/127065/…【参考方案3】:在http://createschema.codeplex.com/ 尝试我的对象的 CreateSchema 扩展方法
它为包含 CREATE TABLE 脚本的任何对象返回一个字符串。
【讨论】:
【参考方案4】:我认为对于复杂的数据类型,您应该通过指定一个 ToDB() 方法来扩展它们,该方法拥有自己的用于在数据库中创建表的实现,这样它就变成了自动递归的。
【讨论】:
【参考方案5】:截至 2016 年(我认为),您可以使用 Entity Framework 6 Code First 从 poco c# 类生成 SQL 模式,或者使用 Database First 从 sql 生成 c# 代码。 Code First to DB walkthrough
【讨论】:
【参考方案6】:对于复杂类型,您可以递归地将遇到的每个类型转换为自己的表,然后尝试管理外键关系。
您可能还想预先指定哪些类将或不会转换为表格。对于您希望在不使架构膨胀的情况下反映在数据库中的复杂数据,您可以拥有一个或多个用于杂项类型的表。此示例使用多达 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(...)
)
【讨论】:
【参考方案7】:另外...也许您可以使用诸如 Visio 之类的工具(不确定 Visio 是否这样做,但我认为确实如此)将您的类逆向工程为 UML,然后使用 UML 生成 DB Schema...或者可以使用诸如 http://www.tangiblearchitect.net/visual-studio/ 之类的工具
【讨论】:
【参考方案8】:我知道您正在寻找一个完整的持久层,但是 NHibernate 的 hbm2ddl 任务几乎可以作为一个单行来完成。
有一个NAnt task 可以调用它,这可能很有趣。
【讨论】:
【参考方案9】:Subsonic 也是另一种选择。我经常使用它来生成映射到数据库的实体类。它有一个命令行实用程序,可让您指定表、类型和许多其他有用的东西
【讨论】:
【参考方案10】:有一个免费的应用程序,Schematrix,它可以从 DB 生成类,看看是否也有相反的效果 :) http://www.schematrix.com/products/schemacoder/download.aspx
【讨论】:
【参考方案11】:试用 .net 的 DaoliteMappingTool。它可以帮助您生成类。 下载表格Here
【讨论】:
【参考方案12】:您可以在此处执行相反的操作,将数据库表转换为 C# 类: http://pureobjects.com/dbCode.aspx
【讨论】:
Title = "How can I generate database tables from C# classes?", 他为什么要反其道而行之?以上是关于如何从 C# 类生成数据库表?的主要内容,如果未能解决你的问题,请参考以下文章